diff --git a/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/01_data_pump_utility.mdx b/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/01_data_pump_utility.mdx index 9e47f70f30f..fd2682924ec 100644 --- a/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/01_data_pump_utility.mdx +++ b/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/01_data_pump_utility.mdx @@ -1,6 +1,6 @@ --- title: "Extracting schemas using Oracle Data Pump utilities" - +navTitle: Using Oracle Data Pump --- Migration Portal requires only the metadata in the SQL dump file to assess the extracted schemas. diff --git a/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/edb_ddl_extractor.mdx b/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/edb_ddl_extractor.mdx new file mode 100644 index 00000000000..487738b8be4 --- /dev/null +++ b/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/edb_ddl_extractor.mdx @@ -0,0 +1,111 @@ +--- +title: "Extracting schemas using the EDB DDL Extractor" +navTitle: Using EDB DDL Extractor +--- + + +Download the latest EDB DDL Extractor script from the Migration Portal Projects page. + +!!! Note + Migration Portal might become unresponsive for very large SQL files, depending on your system and browser resource availability. To resolve this, try extracting fewer schemas at a time to reduce the SQL file size. + +## Prerequisites + +You can run the EDB DDL Extractor script in SQL Developer or SQL\*Plus. It uses Oracle’s `DBMS_METADATA` built-in package to extract DDLs for different objects under schemas (specified while running the script). The EDB DDL Extractor creates the DDL file uploaded to the portal and analyzed for EDB Postgres Advanced Server compatibility. + +!!! Note + You must have `CONNECT` and `SELECT_CATALOG_ROLE` roles and `CREATE TABLE` privilege. + +### For SQL\*Plus + +1. Connect to SQL\*Plus and run this command: + + ```sql + @edb_ddl_extractor.sql + ``` + +1. When prompted, if the Oracle user that is running the script has the required privileges, press **Enter** to continue running the script. + +1. When prompted, provide the schema name. When extracting multiple schemas, use a comma (`‘,’`) as a delimiter. + + !!! Note + If you want to extract all the user schemas from the current database, don't mention any schema names while extracting. However, we recommend mentioning the schema names that you want to extract. + +1. When prompted, enter the path or directory for the extractor to store the extracted DDL. If you don't specify a path, the extracted DDL is output to the directory where you ran the SQL\*Plus command. + +1. When prompted, enter `yes`or `no` depending on whether you want to extract dependent objects from other schemas. + +1. When prompted, enter `yes`or `no` depending on whether you want to extract grant statements from other schemas. + +## Example + +1. Run the extractor script: + + ```text + @edb_ddl_extractor.sql + ``` + +1. Press **Enter**. + +1. Specify three schemas by separating them with commas: + + ```text + Enter a comma separated list of schemas to be extracted (Default all schemas): HR, SCOTT, FINANCE + ``` + +1. Enter a path for the output file: + + On Linux, you might use: + + ```text + Location for output file (Default current location) : /home/oracle/extracted_ddls/ + ``` + + Similarly on Windows: + + ```text + Location for output file (Default current location) : c:\Users\Example\Desktop\ + ``` + +1. Enter `yes` to extract dependent objects in other schemas: + + ```text + WARNING: + + Given schema(s) list may contain objects which are dependent on objects + from other schema(s), not mentioned in the list.` `Assessment may fail + for such objects. It is suggested to extract all dependent objects + together. + Extract dependent object from other schemas?(yes/no) (Default no / Ignored for all schemas option): yes + ``` + +1. Enter `yes` to extract grant statements: + + ```text + Extract GRANT statements?(yes/no) (Default no): yes + ``` + +### For SQL Developer + +After loading the `edb_ddl_extractor.sql` script into SQL Developer and connecting to the source Oracle database, run the script. As the script executes, respond to the prompts. + +1. If the user for the database connection has the required privileges as listed in the **Script Output** tab, select **Yes** to continue running the script. + +2. Enter a comma-separated list of schemas, and select **OK**. + +3. Enter the path for the output file, and select **OK**. The default is the location of the DDL Extractor script. + +4. Enter `yes` or `no` to extract dependent objects, and select **OK**. The default is to not extract dependent objects. + +5. Enter `yes` or `no` to extract grant statements, and select **OK**. The default setting is not to extract grant statements. + +Output of the DDL Extractor run appears in the Script Output tab. The name of the output file appears after the `Extraction Completed` message in the script output. + +!!! Note + You can also enter single schema name in both SQL\*Plus and SQL Developer. + +The script then iterates through the object types in the source database. Once the task is completed, the `.SQL` output is stored at the location you entered (e.g., `c:\Users\Example\Desktop\`). + +See [file encoding](/migration_portal/latest/known_issues_notes/#file-encoding) for information about the file encoding format expected by Migration Portal. + + diff --git a/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/index.mdx b/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/index.mdx index e3fe205e35e..30953d039ec 100644 --- a/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/index.mdx +++ b/product_docs/docs/migration_portal/4/04_mp_migrating_database/01_mp_schema_extraction/index.mdx @@ -7,126 +7,27 @@ legacyRedirectsGenerated: redirects: - ../01_whats_new/ - +deepToC: true navigation: - - "01_data_pump_utility" - + - edb_ddl_extractor + - 01_data_pump_utility --- - - -You can perform a schema extraction using either of the following methods. EDB recommends using the EDB DDL extractor to extract your schemas. - - [EDB DDL Extractor](#extracting-schemas-using-the-edb-ddl-extractor) (recommended method) - - [Oracle Data Pump utilities](01_data_pump_utility/) - -For more information, see [Known issues, limitations, and notes](/migration_portal/latest/known_issues_notes/). - -## Extracting schemas using the EDB DDL Extractor - -Download the latest EDB DDL Extractor script from the Migration Portal Projects page. - -!!! Note - Migration Portal might become unresponsive for very large SQL files, depending on your system and browser resource availability. To resolve this, try extracting fewer schemas at a time to reduce the SQL file size. - -### Prerequisites - -You can run the EDB DDL Extractor script in SQL Developer or SQL\*Plus. It uses Oracle’s `DBMS_METADATA` built-in package to extract DDLs for different objects under schemas (specified while running the script). The EDB DDL Extractor creates the DDL file uploaded to the portal and analyzed for EDB Postgres Advanced Server compatibility. - -!!! Note - You must have `CONNECT` and `SELECT_CATALOG_ROLE` roles and `CREATE TABLE` privilege. - -#### For SQL\*Plus - -1. Connect to SQL\*Plus and run this command: - - ```sql - @edb_ddl_extractor.sql - ``` - -2. When prompted, if the Oracle user that is running the script has the required privileges, press **Enter** to continue running the script. - -3. When prompted, provide the schema name. When extracting multiple schemas, use a comma (`‘,’`) as a delimiter. - - !!! Note - If you want to extract all the user schemas from the current database, don't mention any schema names while extracting. However, we recommend mentioning the schema names that you want to extract. - -4. When prompted, enter the path or directory for the extractor to store the extracted DDL. If you don't specify a path, the extracted DDL is output to the directory where you ran the SQL\*Plus command. - -5. When prompted, enter `yes`or `no` depending on whether you want to extract dependent objects from other schemas. - -6. When prompted, enter `yes`or `no` depending on whether you want to extract grant statements from other schemas. - -For example: - -1. Run the extractor script: +## Schema extraction methods - ```text - @edb_ddl_extractor.sql - ``` +You can perform a schema extraction using the EDB or Oracle extraction tools.Select one of the following for instructions and examples: -2. Press **Enter** - -3. Specify three schemas by separating them with commas: - - ```text - Enter a comma separated list of schemas to be extracted (Default all schemas): HR, SCOTT, FINANCE - ``` - -4. Enter a path for the output file: - - On Linux, you might use: - - ```text - Location for output file (Default current location) : /home/oracle/extracted_ddls/ - ``` - - Similarly on Windows: - - ```text - Location for output file (Default current location) : c:\Users\Example\Desktop\ - ``` - -5. Enter `yes` to extract dependent objects in other schemas: - - ```text - WARNING: - - Given schema(s) list may contain objects which are dependent on objects - from other schema(s), not mentioned in the list.` `Assessment may fail - for such objects. It is suggested to extract all dependent objects - together. - Extract dependent object from other schemas?(yes/no) (Default no / Ignored for all schemas option): yes - ``` - -6. Enter `yes` to extract grant statements: - - ```text - Extract GRANT statements?(yes/no) (Default no): yes - ``` - -#### For SQL Developer - -After loading the `edb_ddl_extractor.sql` script into SQL Developer and connecting to the source Oracle database, run the script. As the script executes, respond to the prompts. - -1. If the user for the database connection has the required privileges as listed in the **Script Output** tab, select **Yes** to continue running the script. - -2. Enter a comma-separated list of schemas, and select **OK**. - -3. Enter the path for the output file, and select **OK**. The default is the location of the DDL Extractor script. - -4. Enter `yes` or `no` to extract dependent objects, and select **OK**. The default is to not extract dependent objects. - -5. Enter `yes` or `no` to extract grant statements, and select **OK**. The default setting is not to extract grant statements. - -Output of the DDL Extractor run appears in the Script Output tab. The name of the output file appears after the `Extraction Completed` message in the script output. - -!!! Note - You can also enter single schema name in both SQL\*Plus and SQL Developer. + - [EDB DDL Extractor](edb_ddl_extractor) (recommended method) + - [Oracle Data Pump utilities](01_data_pump_utility/) -The script then iterates through the object types in the source database. Once the task is completed, the `.SQL` output is stored at the location you entered (e.g., `c:\Users\Example\Desktop\`). +EDB recommends using the EDB DDL extractor to extract your schemas. +Alternatively, you can use Oracle’s Data Pump (IMPDP/EXPDP) tool to export schemas from an Oracle database. -See [file encoding](/migration_portal/latest/known_issues_notes/#file-encoding) for information about the file encoding format expected by Migration Portal. +!!!warning + If you choose to extract schemas using a different method and then upload the DDL file to Migration Portal, the portal may not be able to assess the file correctly. +!!! +For more information, see [Known issues, limitations, and notes](/migration_portal/latest/known_issues_notes/). ## Schemas and objects support diff --git a/product_docs/docs/migration_portal/4/04_mp_migrating_database/index.mdx b/product_docs/docs/migration_portal/4/04_mp_migrating_database/index.mdx index 8836d3f083a..5b8fb87bb4d 100644 --- a/product_docs/docs/migration_portal/4/04_mp_migrating_database/index.mdx +++ b/product_docs/docs/migration_portal/4/04_mp_migrating_database/index.mdx @@ -11,7 +11,7 @@ legacyRedirectsGenerated: To migrate a database, you must complete the following steps: -1. Perform a [schema extraction](01_mp_schema_extraction/#mp_schema_extraction). +1. Perform a [schema extraction](01_mp_schema_extraction). 2. Perform a [schema assessment](02_mp_schema_assessment/#mp_schema_assessment). 3. Perform a [schema migration](03_mp_schema_migration/#mp_schema_migration). 4. Perform a [data migration](04_mp_data_migration/#mp_data_migration). diff --git a/product_docs/docs/net_connector/8.0.5.1/01_release_notes.mdx b/product_docs/docs/net_connector/8.0.5.1/01_release_notes.mdx new file mode 100644 index 00000000000..05fa5f26539 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/01_release_notes.mdx @@ -0,0 +1,17 @@ +--- +title: "Release notes" +--- + +Released: 22 Nov 2024 + +The EDB .NET Connector provides connectivity between a .NET client application and an EDB Postgres Advanced Server database server. + +New features, enhancements, bug fixes, and other changes in the EDB .NET Connector `8.0.5.1` include: + +| Type | Description | Addresses | +|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------| +| Upstream merge | Merged with community .NET driver version 8.0.5 and EF Core Driver 8.0.10. See [release notes](https://www.npgsql.org/doc/release-notes/8.0.html) for more information about merge updates. | | +| Bug fix | Fixed a performance issue. Performance is now improved when reading data while targeting .NET Framework 4.7.2, 4.8, and 4.8.1. | #41979 | +| Enhancement | Added support for EDB Postgres Advanced Server 17.2. | | +| Enhancement | Added support for `IS TABLE OF`. EDB Postgres Advanced Server supports Oracle nested table collection types created with `CREATE TYPE ... AS TABLE OF` statements. See [Using nested tables](./using_nested_table_types.mdx) for more information. | | +| Deprecation | Removed .NET5, .NET6, and .NET7 targets as they have reached end of support. | | \ No newline at end of file diff --git a/product_docs/docs/net_connector/8.0.5.1/02_requirements_overview.mdx b/product_docs/docs/net_connector/8.0.5.1/02_requirements_overview.mdx new file mode 100644 index 00000000000..fbd750391e3 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/02_requirements_overview.mdx @@ -0,0 +1,20 @@ +--- +title: "Product compatibility" +--- + + + +These are the supported versions and platforms for the EDB .NET Connector. + +The EDB .NET Connector is certified with EDB Postgres Advanced Server version 11 and later. + +The EDB .NET Connector graphical installers are supported on the following Windows platforms: + +64-bit Windows: + +- Windows Server 2019 and 2022 +- Windows 10 and 11 + +32-bit Windows: + +- Windows 10 diff --git a/product_docs/docs/net_connector/8.0.5.1/03_the_advanced_server_net_connector_overview.mdx b/product_docs/docs/net_connector/8.0.5.1/03_the_advanced_server_net_connector_overview.mdx new file mode 100644 index 00000000000..edc633b4804 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/03_the_advanced_server_net_connector_overview.mdx @@ -0,0 +1,39 @@ +--- +title: "EDB .NET Connector overview" + +--- + + + +EDB .NET Connector is a .NET data provider that allows a client application to connect to a database stored on an EDB Postgres Advanced Server host. The .NET Connector accesses the data directly, allowing the client application optimal performance, a broad spectrum of functionality, and access to EDB Postgres Advanced Server features. + +The .NET Connector supports the following frameworks: + +- .NET 8.0 +- .NET Framework 4.7.2, 4.8, and 4.8.1 +- .NET Standard 2.0 and 2.1 + + +## The .NET class hierarchy + +The .NET class hierarchy contains classes that you can use to create objects that control a connection to the EDB Postgres Advanced Server database and manipulate the data stored on the server. The following are a few of the most commonly used object classes. + +`EDBDataSource` + + `EDBDataSource` is the entry point for all the connections made to the database. It's responsible for issuing connections to the server and efficiently managing them. Starting with EDB .NET Connector 7.0.4.1, you no longer need direct instantiation of `EDBConnection`. Instantiate `EDBDataSource` and use the method provided to create commands or execute queries. + +`EDBConnection` + + The `EDBConnection` class represents a connection to EDB Postgres Advanced Server. An `EDBConnection` object contains a `ConnectionString` that tells the .NET client how to connect to an EDB Postgres Advanced Server database. Obtain `EDBConnection` from an `EDBDataSource` instance, and use it directly only in specific scenarios, such as transactions. + +`EDBCommand` + + An `EDBCommand` object contains a SQL command that the client executes against EDB Postgres Advanced Server. Before you can execute an `EDBCommand` object, you must link it to an `EDBConnection` object. + +`EDBDataReader` + + An `EDBDataReader` object provides a way to read an EDB Postgres Advanced Server result set. You can use an `EDBDataReader` object to step through one row at a time, forward only. + +`EDBDataAdapter` + + An `EDBDataAdapter` object links a result set to the EDB Postgres Advanced Server database. You can modify values and use the `EDBDataAdapter` class to update the data stored in an EDB Postgres Advanced Server database. diff --git a/product_docs/docs/net_connector/8.0.5.1/04_installing_and_configuring_the_net_connector.mdx b/product_docs/docs/net_connector/8.0.5.1/04_installing_and_configuring_the_net_connector.mdx new file mode 100644 index 00000000000..32b80812cf3 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/04_installing_and_configuring_the_net_connector.mdx @@ -0,0 +1,290 @@ +--- +title: "Installing and configuring the .NET Connector" + +--- + + + +## Installing the .NET Connector + +You can install the EDB .NET Connector using either the EDB installer or the installer from NuGet.org. + +### Installing and configuring the .NET Connector from NuGet.org + +#### Install NuGet package via command line + +Launch a terminal from your solution folder and run: + +```text +dotnet add package EnterpriseDB.EDBClient +``` + +This command downloads and installs the EDB .NET Connector matching your .NET version. Your project is then ready to import the EDB .NET Connector namespace: + +```text +using EnterpriseDB.EDBClient; +``` + +You can find all the EDB .NET Connector satellite packages at [NuGet.org](https://www.nuget.org/profiles/EnterpriseDB). + +For more information, see the [EDB .NET Connector Now Published on NuGet](https://www.enterprisedb.com/blog/improving-developer-experience-updated-edb-net-connector-now-published-nuget) blog post. + +#### Install NuGet package via Visual Studio interface + +1. Right-click your project or solution and select **Manage NuGet package**. +1. Search the package using `enterprisedb.edbclient` as the search text. +1. Select the EnterpriseDB.EDBClient package. +1. Select **Install** to proceed to package download and installation. + +This command downloads and installs the EDB .NET Connector matching your .NET version. Your project is then ready to import the EDB .NET Connector namespace: + +```text +using EnterpriseDB.EDBClient; +``` + +For more information, see the [EDB .NET Connector Now Published on NuGet](https://www.enterprisedb.com/blog/improving-developer-experience-updated-edb-net-connector-now-published-nuget) blog post. + +### Installing the .NET Connector using EDB installer + +You can use the EDB .NET Connector installer to add the .NET Connector to your system. The installer is available from [the EDB website](https://www.enterprisedb.com/software-downloads-postgres). + +1. After downloading the installer, right-click the installer icon, and select **Run As Administrator**. When prompted, select an installation language and select **OK** to continue to the Setup window. + + ![The .NET Connector Installation wizard](images/dotnet_installation_wizard.png) + +1. Select **Next**. + + ![The Installation dialog box](images/dotnet_installation_dialog.png) + +1. Use the Installation Directory dialog box to specify the directory in which to install the connector. Select **Next**. + + ![The Ready to Install dialog box](images/ready_to_install.png) + +1. To start the installation, on the Ready to Install dialog box, select **Next**. Popups confirm the progress of the installation wizard. + + ![The installation is complete](images/dotnet_installation_complete.png) + +1. When the wizard informs you that it has completed the setup, select **Finish**. + +You can also use StackBuilder Plus to add or update the connector on an existing EDB Postgres Advanced Server installation. + +1. To open StackBuilder Plus, from the Windows **Apps** menu, select **StackBuilder Plus**. + + ![Starting StackBuilder Plus](images/starting_stackbuilder_plus.png) + +1. When StackBuilder Plus opens, follow the onscreen instructions. + +1. From the Database Drivers node of the tree control, select the **EnterpriseDB.Net Connector** option. + + ![Selecting the Connectors installer](images/selecting_the_connectors_installer.png) + +1. Follow the directions of the onscreen wizard to add or update an installation of an EDB Connector. + +### Configuring the .NET Connector + +For information about configuring the .NET Connector in each environment, see: + +- **Referencing the Library Files.** [General configuration information](#referencing_the_library_files) applicable to all components. +- **.NET 8.0** Instructions for configuring for use with [.NET 8.0](#setup_8_0). +- **.NET Framework 4.7.2** Instructions for configuring for use with [.NET framework 4.7.2](#net-framework-472). +- **.NET Framework 4.8** Instructions for configuring for use with [.NET Framework 4.8](#net-framework-48). +- **.NET Framework 4.8.1** Instructions for configuring for use with [.NET Framework 4.8.1](#net-framework-481). +- **.NET Standard 2.0** Instructions for configuring for use with [.NET Standard 2.0](#standard_setup_2_0). +- **.NET Standard 2.1** Instructions for configuring for use with [.NET Standard 2.1](#standard_setup_2_1). +- **.NET EntityFramework Core** Instructions for configuring for use with [.NET EntityFramework Core](#entity_setup). + +#### Referencing the library files + + + +To reference library files with Microsoft Visual Studio: + +1. In the Solution Explorer, select the project. +2. Select **Project > Add Reference**. +3. In the Add Reference dialog box, browse to select the appropriate library files. + +Optionally, you can copy the library files to the specified location. + +Before you can use an EDB .NET class, you must import the namespace into your program. Importing a namespace makes the compiler aware of the classes available in the namespace. The namespace is `EnterpriseDB.EDBClient`. + +The method you use to include the namespace varies by the type of application you're writing. For example, the following command imports a namespace into an `ASP.NET` page: + +```text + <% import namespace="EnterpriseDB.EDBClient" %> +``` + +To import a namespace into a C# application, use: + +```text + using EnterpriseDB.EDBClient; +``` + +#### .NET framework setup + +Each .NET version has specific setup instructions. + + + +##### .NET 8.0 + +For .NET 8.0, the data provider installation path is: + +`C:\Program Files\edb\dotnet\net8.0\` + +You must add the following dependencies to your project: + +`EnterpriseDB.EDBClient.dll` + +Depending upon the type of application you use, you may be required to import the namespace into the source code. See [Referencing the library files](#referencing_the_library_files) for this and other information about referencing library files. + +##### .NET Framework 4.7.2 + +For .NET Framework 4.7.2, the data provider installation path is: + + `C:\Program Files\edb\dotnet\net472\`. + +You must add the following dependency to your project. You may also need to add other dependencies from the same directory: + +- `EnterpriseDB.EDBClient.dll` + +Depending on your application type, you might need to import the namespace into the source code. See [Referencing the library files](#referencing_the_library_files) for this and the other information about referencing the library files. + +##### .NET Framework 4.8 + +For .NET Framework 4.8, the data provider installation path is: + + `C:\Program Files\edb\dotnet\net48\`. + +You must add the following dependency to your project. You may also need to add other dependencies from the same directory: + +- `EnterpriseDB.EDBClient.dll` + +Depending on your application type, you might need to import the namespace into the source code. See [Referencing the library files](#referencing_the_library_files) for this and the other information about referencing the library files. + +##### .NET Framework 4.8.1 + +For .NET Framework 4.8.1, the data provider installation path is: + + `C:\Program Files\edb\dotnet\net481\`. + +You must add the following dependency to your project. You may also need to add other dependencies from the same directory: + +- `EnterpriseDB.EDBClient.dll` + +Depending on your application type, you might need to import the namespace into the source code. See [Referencing the library files](#referencing_the_library_files) for this and the other information about referencing the library files. + + + +##### .NET Standard 2.0 + +For .NET Standard Framework 2.0, the data provider installation path is: + + `C:\Program Files\edb\dotnet\netstandard2.0\`. + +You must add the following dependencies to your project: + +- `EnterpriseDB.EDBClient.dll` + +- `System.Threading.Tasks.Extensions.dll` + +- `System.Runtime.CompilerServices.Unsafe.dll` + +- `System.ValueTuple.dll` + +Depending on your application type, you might need to import the namespace into the source code. See [Referencing the library files](#referencing_the_library_files) for this and the other information about referencing the library files. + + + +##### .NET Standard 2.1 + +For .NET Standard Framework 2.1, the data provider installation path is `C:\Program Files\edb\dotnet\netstandard2.1\`. + +The following shared library files are required: + +- `EnterpriseDB.EDBClient.dll` + +- `System.Memory.dll` + +- `System.Runtime.CompilerServices.Unsafe.dll` + +- `System.Text.Json.dll` + +- `System.Threading.Tasks.Extensions.dll` + +- `System.ValueTuple.dll` + +Depending on your application type, you might need to import the namespace into the source code. See [Referencing the library files](#referencing_the_library_files) for this and the other information about referencing the library files. + + + +##### .NET Entity Framework Core + +To configure the .NET Connector for use with Entity Framework Core, the data provider installation path is: + +`C:\Program Files\edb\dotnet\EF.Core\EFCore.PG\net8.0` +The following shared library file is required: + +- `EnterpriseDB.EDBClient.EntityFrameworkCore.PostgreSQL.dll` + +See [Referencing the library files](#referencing_the_library_files) for information about referencing the library files. + +The following NuGet packages are required: + +- `Microsoft.EntityFrameworkCore.Design` + +- `Microsoft.EntityFrameworkCore.Relational` + +- `Microsoft.EntityFrameworkCore.Abstractions` + + +For usage information about Entity Framework Core, see the [Microsoft documentation](https://learn.microsoft.com/en-us/ef/core/). + +**Prerequisite** + +To open a command prompt: + +Select **Tools > Command Line > Developer Command Prompt**. + +Install dotnet-ef (using the command prompt), + + `dotnet tool install --global dotnet-ef` + +**Sample project** + +Create a new Console Application based on .NET 8.0. + +Add Reference to the following EDB assemblies: + +- `EnterpriseDB.EDBClient.EntityFrameworkCore.PostgreSQL.dll` + +- `EnterpriseDB.EDBClient.dll` + +Add the following NuGet packages: + +- `Microsoft.EntityFrameworkCore.Design` + +- `Microsoft.EntityFrameworkCore.Relational` + +- `Microsoft.EntityFrameworkCore.Abstractions` + +**Database-first scenario** + +Issue the following command to create model classes corresponding to all objects in the specified database: + +```text +dotnet ef dbcontext scaffold Host=;Database=;Username=;Password=;Port= EnterpriseDB.EDBClient.EntityFrameworkCore.PostgreSQL -o Models +``` + +**Code-first scenario** + +Add code for defining a DbContext and create, read, update, and delete operations. + +For more details, see the Microsoft documentation. + +Issue the following commands to create the initial database and tables: + +```text + dotnet ef migrations add InitialCreate --context BloggingContext + + dotnet ef database update --context BloggingContext +``` diff --git a/product_docs/docs/net_connector/8.0.5.1/05_using_the_net_connector.mdx b/product_docs/docs/net_connector/8.0.5.1/05_using_the_net_connector.mdx new file mode 100644 index 00000000000..bba3c8d70ec --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/05_using_the_net_connector.mdx @@ -0,0 +1,24 @@ +--- +title: "Using the .NET Connector" + +--- + + + +These examples show how you can use the EDB object classes that are provided by the EDB .NET Connector. These object classes allow a .NET application to connect to and interact with an EDB Postgres Advanced Server database. + +To use these examples, place the .NET library files in the same directory as the compiled form of your application. All of these examples are written in C#, and each is embedded in an ASP.NET page. The same logic and code applies to other .NET applications (WinForm or console applications, for example). + +Create and save the following `web.config` file in the same directory as the sample code. The examples make use of the `DB_CONN_STRING` key from this configuration file to return a connection string from the EDB Postgres Advanced Server host. + +```text + + + + + + +``` + +An EDB Postgres Advanced Server connection string for an ASP.NET web application is stored in the `web.config` file. If you're writing an application that doesn't use ASP.NET, provide the connection information in an application configuration file, such as `app.config`. diff --git a/product_docs/docs/net_connector/8.0.5.1/06_opening_a_database_connection.mdx b/product_docs/docs/net_connector/8.0.5.1/06_opening_a_database_connection.mdx new file mode 100644 index 00000000000..b1a8da3eca9 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/06_opening_a_database_connection.mdx @@ -0,0 +1,278 @@ +--- +title: "Opening a database connection" + +--- + + + +An `EDBConnection` object is responsible for handling the communication between an instance of EDB Postgres Advanced Server and a .NET application. Before you can access data stored in an EDB Postgres Advanced Server database, you must create and open an `EDBConnection` object. + +## Creating an EDBConnection object + +You can open a connection using one of the following approaches. In either case, you must import the namespace `EnterpriseDB.EDBClient`. + +### Connection with a data source + +1. Create an instance of the `EDBDataSource` object using a connection string as a parameter to the create method of the `EDBDataSource` class. + +2. To open a connection, call the `OpenConnection` method of the `EDBDataSource` object. + +This example shows how to open a connection using a data source: + + ```text + await using var dataSource = EDBDataSource.Create(ConnectionString); + var connection = dataSource.OpenConnection(); + ``` + +### Connection without a data source + +1. Create an instance of the `EDBConnection` object using a connection string as a parameter to the constructor of the `EDBConnection` class. + +2. Call the `Open` method of the `EDBConnection` object to open the connection. + +This example shows how to open a connection without a data source: + + ```text + EDBConnection conn = new EDBConnection(ConnectionString); + conn.Open(); + ``` + +!!! Note + For `EnterpriseDB.EDBClient 7.0.4` and later, we recommend `EDBDataSource` to connect to EDB Postgres Advanced Server database or execute SQL directly against it. For more information on the data source, see the [Npgsql documentation](https://www.npgsql.org/doc/basic-usage.html). + + + + +## Connection string parameters + +A valid connection string specifies location and authentication information for an EDB Postgres Advanced Server instance. You must provide the connection string before opening the connection. A connection string must contain: + +- The name or IP address of the server +- The name of the EDB Postgres Advanced Server database +- The name of an EDB Postgres Advanced Server user +- The password associated with that user + +You can include the following parameters in the connection string: + +`CommandTimeout` + + `CommandTimeout` specifies the length of time (in seconds) to wait for a command to finish executing before throwing an exception. The default value is `20`. + +`ConnectionLifeTime` + + Use `ConnectionLifeTime` to specify the length of time (in seconds) to wait before closing unused connections in the pool. The default value is `15`. + +`Database` + + Use the `Database` parameter to specify the name of the database for the application to connect to. The default is the name of the connecting user. + +`Encoding` + + The `Encoding` parameter is obsolete. The parameter always returns the string `unicode` and silently ignores attempts to set it. + +`Integrated Security` + + Specify a value of `true` to use Windows Integrated Security. By default, `Integrated Security` is set to `false`, and Windows Integrated Security is disabled. + +`Load Role Based Tables` + + Use `Load Role Based Tables` to load table OIDs based on role. This change affects only the loading of table type OID and not the composite type. Setting this parameter to `true` triggers the new functionality. The default value is `false`. + +`MaxPoolSize` + + `MaxPoolSize` instructs `EDBConnection` to dispose of pooled connections when the pool exceeds the specified number of connections. The default value is `20`. + +`MinPoolSize` + + `MinPoolSize` instructs `EDBConnection` to preallocate the specified number of connections with the server. The default value is `1`. + +`Password` + + When using clear text authentication, specify the password to use to establish a connection with the server. + +`Pooling` + + Specify a value of `false` to disable connection pooling. By default, `Pooling` is set to `true` to enable connection pooling. + +`No Reset On Close` + +When `Pooling` is enabled and the connection is closed, reopened, and the underlying connection is reused, then some operations are executed to discard the previous connection resources. You can override this behavior by enabling `No Reset On Close`. + +`Port` + + The `Port` parameter specifies the port for the application to connect to. + +`Protocol` + + The specific protocol version to use (instead of automatic). Specify an integer value of `2` or `3`. + +`SearchPath` + + Use the `SearchPath` parameter to change the search path to named and public schemas. + +`Server` + + The name or IP address of the EDB Postgres Advanced Server host. + +`SSL` + + Specify a value of `true` to attempt a secure connection. By default, `SSL` is set to `false`. + +`sslmode` + + Use `sslmode` to specify an SSL connection control preference. `sslmode` can be: + +- `prefer` — Use SSL if possible. + +- `require` — Throw an exception if an SSL connection can't be established. + +- `allow` — Connect without SSL. This parameter isn't supported. + +- `disable` — Don't attempt an SSL connection. This is the default behavior. + +`SyncNotification` + + Use the `SyncNotification` parameter to specify for `EDBDataprovider` to use synchronous notifications. The default value is `false`. + +`Timeout` + + `Timeout` specifies the length of time (in seconds) to wait for an open connection. The default value is `15`. + +`User Id` + + The `User Id` parameter specifies the user name to use for the connection. + +## Example: Opening a database connection using ASP.NET + +This example shows how to open a connection to an instance of EDB Postgres Advanced Server and then close the connection. The connection is established using the credentials specified in the `DB_CONN_STRING` configuration parameter. See [Using the .Net Connector](05_using_the_net_connector/#using_the_net_connector) for an introduction to connection information. Also see [Connection string parameters](#connection-string-parameters) for connection parameters. + +```cpp +<% @ Page Language="C#" %> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Configuration" %> + +``` + +If the connection is successful, a message appears indicating that the connection opened successfully. + +## Example: Opening a database connection from a console application + +This example opens a connection with an EDB Postgres Advanced Server database using a console-based application. + +Before writing the code for the console application, create an `app.config` file that stores the connection string to the database. Using a configuration file makes it convenient to update the connection string if the information changes. + +```ini + + + + + + +``` + +Enter the following code sample into a file: + +```csharp +using System; +using System.Data; +using EnterpriseDB.EDBClient; +using System.Configuration; +namespace EnterpriseDB +{ + class EDB + { + static void Main(string[] args) + { + var strConnectionString = ConfigurationManager.AppSettings["DB_CONN_STRING"]; + try + { + await using var dataSource = EDBDataSource.Create(strConnectionString); + var conn = dataSource.OpenConnection(); + Console.WriteLine("Connection Opened Successfully"); + conn.Close(); + } + catch(Exception exp) + { + throw new Exception(exp.ToString()); + } + } + } +} +``` + +Save the file as `EDBConnection-Sample.cs` and compile it with the following command: + +```text +csc /r:EnterpriseDB.EDBClient.dll /out:Console.exe EDBConnection-Sample.cs` +``` + +Compiling the sample generates a `Console.exe` file. You can execute the sample code by entering `Console.exe`. When executed, the console verifies that it opened successfully. + +## Example: Opening a database connection from a Windows form application + +This example opens a database connection using a .NET WinForm application. To use the example, save the following code as `WinForm-Example.cs` in a directory that contains the library files: + +```csharp +using System; +using System.Windows.Forms; +using System.Drawing; +using EnterpriseDB.EDBClient; +namespace EDBTestClient +{ + class Win_Conn + { + static void Main(string[] args) + { + Form frmMain = new Form(); + Button btnConn = new Button(); + btnConn.Location = new System.Drawing.Point(104, 64); + btnConn.Name = "btnConn"; + btnConn.Text = "Open Connection"; + btnConn.Click += new System.EventHandler(btnConn_Click); + frmMain.Controls.Add(btnConn); + frmMain.Text = "EnterpriseDB"; + Application.Run(frmMain); + } + private static void btnConn_Click(object sender, System.EventArgs e) + { + try + { + var strConnectionString = "Server=localhost;port=5444;username=edb;password=edb;database=edb"; + await using var dataSource = EDBDataSource.Create(strConnectionString); + var conn = dataSource.OpenConnection(); + MessageBox.Show("Connection Opened Successfully"); + conn.Close(); + } + catch(EDBException exp) + { + MessageBox.Show(exp.ToString()); + } + } + } +} +``` + +Change the database connection string to point to the database that you want to connect to. Then compile the file with the following command: + +```text +csc /r:EnterpriseDB.EDBClient.dll /out:WinForm.exe WinForm-Example.cs +``` + +This command generates a `WinForm.exe` file in the same folder that the executable was compiled under. Invoking the executable displays a message that the connection was successful. diff --git a/product_docs/docs/net_connector/8.0.5.1/07_retrieving_database_records.mdx b/product_docs/docs/net_connector/8.0.5.1/07_retrieving_database_records.mdx new file mode 100644 index 00000000000..5f929c75050 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/07_retrieving_database_records.mdx @@ -0,0 +1,102 @@ +--- +title: "Retrieving database records" + +--- + + + +You can use a `SELECT` statement to retrieve records from the database using a `SELECT` command. To execute a `SELECT` statement you must: + +1. Create and open a database connection. +1. Create an `EDBCommand` object that represents the `SELECT` statement. +1. Execute the command with the `ExecuteReader()` method of the `EDBCommand` object returning `EDBDataReader`. +1. Loop through the `EDBDataReader`, displaying the results or binding the `EDBDataReader` to some control. + +An `EDBDataReader` object represents a forward-only and read-only stream of database records, presented one record at a time. To view a subsequent record in the stream, you must call the `Read()` method of the `EDBDataReader` object. + +The example that follows: + +1. Imports the EDB Postgres Advanced Server namespace `EnterpriseDB.EDBClient`. +2. Initializes an `EDBCommand` object with a `SELECT` statement. +3. Opens a connection to the database. +4. Executes the `EDBCommand` by calling the `ExecuteReader` method of the `EDBCommand` object. + +The results of the SQL statement are retrieved into an `EDBDataReader` object. + +Loop through the contents of the `EDBDataReader` object to display the records returned by the query in a `WHILE` loop. + +The `Read()` method advances to the next record (if there is one) and returns `true` if a record exists. It returns `false` if `EDBDataReader` has reached the end of the result set. + +```cpp +<% @ Page Language="C#" %> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + + +``` + +To exercise the sample code, save the code in your default web root directory in a file named `selectEmployees.aspx`. Then, to invoke the program, enter the following in a browser: `http://localhost/selectEmployees.aspx`. + +## Retrieving a single database record + +To retrieve a single result from a query, use the `ExecuteScalar()` method of the `EDBCommand` object. The `ExecuteScalar()` method returns the first value of the first column of the first row of the `DataSet` generated by the specified query. + +```cpp +<% @ Page Language="C#" %> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +Save the sample code in a file named `selectscalar.aspx` in a web root directory. + +To invoke the sample code, enter the following in a browser: `http://localhost/selectScalar.aspx` + +The sample includes an explicit conversion of the value returned by the `ExecuteScalar()` method. The `ExecuteScalar()` method returns an object. To view the object, you must convert it to an integer value by using the `Convert.ToInt32` method. diff --git a/product_docs/docs/net_connector/8.0.5.1/08_parameterized_queries.mdx b/product_docs/docs/net_connector/8.0.5.1/08_parameterized_queries.mdx new file mode 100644 index 00000000000..c6e393c296f --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/08_parameterized_queries.mdx @@ -0,0 +1,47 @@ +--- +title: "Parameterized queries" + +--- + + + +A _parameterized query_ is a query with one or more parameter markers embedded in the SQL statement. Before executing a parameterized query, you must supply a value for each marker found in the text of the SQL statement. + +Parameterized queries are useful when you don't know the complete text of a query when you write your code. For example, the value referenced in a `WHERE` clause can be calculated from user input. + +As shown in the following example, you must declare the data type of each parameter specified in the parameterized query by creating an `EDBParameter` object and adding that object to the command's parameter collection. Then, you must specify a value for each parameter by calling the parameter's `Value()` function. + +The example shows using a parameterized query with an `UPDATE` statement that increases an employee salary: + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +Save the sample code in a file named `updateSalary.aspx` in a web root directory. + +To invoke the sample code, enter the following in a browser: `http://localhost/updateSalary.aspx` diff --git a/product_docs/docs/net_connector/8.0.5.1/09_inserting_records_in_a_database.mdx b/product_docs/docs/net_connector/8.0.5.1/09_inserting_records_in_a_database.mdx new file mode 100644 index 00000000000..228224eb3b8 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/09_inserting_records_in_a_database.mdx @@ -0,0 +1,47 @@ +--- +title: "Inserting records in a database" + +--- + + + +You can use the `ExecuteNonQuery()` method of `EDBCommand` to add records to a database stored on an EDB Postgres Advanced Server host with an `INSERT` command. + +In the example that follows, the `INSERT` command is stored in the variable `cmd`. The values prefixed with a colon (`:`) are placeholders for `EDBParameters` that are instantiated, assigned values, and then added to the `INSERT` command's parameter collection in the statements that follow. The `INSERT` command is executed by the `ExecuteNonQuery()` method of the `cmdInsert` object. + +The example adds an employee to the `emp` table: + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +Save the sample code in a file named `insertEmployee.aspx` in a web root directory. + +To invoke the sample code, enter the following in a browser: `http://localhost/insertEmployee.aspx` diff --git a/product_docs/docs/net_connector/8.0.5.1/10_deleting_records_in_a_database.mdx b/product_docs/docs/net_connector/8.0.5.1/10_deleting_records_in_a_database.mdx new file mode 100644 index 00000000000..8c797af0868 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/10_deleting_records_in_a_database.mdx @@ -0,0 +1,44 @@ +--- +title: "Deleting records in a database" + +--- + + + +You can use the `ExecuteNonQuery()` method of `EDBCommand` to delete records from a database stored on an EDB Postgres Advanced Server host with a `DELETE` statement. + +In the example that follows, the `DELETE` command is stored in the variable `strDeleteQuery`. The code passes the employee number specified by `EmpNo` to the `DELETE` command. The command is then executed using the `ExecuteNonQuery()` method. + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +Save the sample code in a file named `deleteEmployee.aspx` in a web root directory. + +To invoke the sample code, enter the following in a browser: `http://localhost/deleteEmployee.aspx` diff --git a/product_docs/docs/net_connector/8.0.5.1/11_using_spl_stored_procedures_in_your_net_application.mdx b/product_docs/docs/net_connector/8.0.5.1/11_using_spl_stored_procedures_in_your_net_application.mdx new file mode 100644 index 00000000000..656a3f32936 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/11_using_spl_stored_procedures_in_your_net_application.mdx @@ -0,0 +1,340 @@ +--- +title: "Using SPL stored procedures in your .NET application" + +--- + + + +You can include SQL statements in an application in two ways: + +- By adding the SQL statements directly in the .NET application code +- By packaging the SQL statements in a stored procedure and executing the stored procedure from the .NET application + +In some cases, a stored procedure can provide advantages over embedded SQL statements. Stored procedures support complex conditional and looping constructs that are difficult to duplicate with SQL statements embedded directly in an application. + +You can also see an improvement in performance by using stored procedures. A stored procedure needs to be parsed, compiled, and optimized only once on the server side. A SQL statement that's included in an application might be parsed, compiled, and optimized each time it's executed from a .NET application. + +To use a stored procedure in your .NET application you must: + +1. Create an SPL stored procedure on the EDB Postgres Advanced Server host. +2. Import the `EnterpriseDB.EDBClient` namespace. +3. Pass the name of the stored procedure to the instance of the `EDBCommand`. +4. Change the `EDBCommand.CommandType` to `CommandType.StoredProcedure`. +5. `Prepare()` the command. +6. Execute the command. + +## Example: Executing a stored procedure without parameters + +This sample procedure prints the name of department 10. The procedure takes no parameters and returns no parameters. To create the sample procedure, invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Enter the following SPL code at the command line: + +```sql +CREATE OR REPLACE PROCEDURE list_dept10 +IS + v_deptname VARCHAR2(30); +BEGIN + DBMS_OUTPUT.PUT_LINE('Dept No: 10'); + SELECT dname INTO v_deptname FROM dept WHERE deptno = 10; + DBMS_OUTPUT.PUT_LINE('Dept Name: ' || v_deptname); +END; +``` + +When EDB Postgres Advanced Server validates the stored procedure, it echoes `CREATE PROCEDURE`. + +### Using the EDBCommand object to execute a stored procedure + +The `CommandType` property of the `EDBCommand` object indicates the type of command being executed. The `CommandType` property is set to one of three possible `CommandType` enumeration values: + +- Use the default `Text` value when passing a SQL string for execution. +- Use the `StoredProcedure` value, passing the name of a stored procedure for execution. +- Use the `TableDirect` value when passing a table name. This value passes back all records in the specified table. + +The `CommandText` property must contain a SQL string, stored procedure name, or table name, depending on the value of the `CommandType` property. + +This example executes the stored procedure: + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +Save the sample code in a file named `storedProc.aspx` in a web root directory. + +To invoke the sample code, enter the following in a browser: `http://localhost/storedProc.aspx` + +## Example: Executing a stored procedure with IN parameters + +This example calls a stored procedure that includes `IN` parameters. To create the sample procedure, invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Enter the following SPL code at the command line: + +```sql +CREATE OR REPLACE PROCEDURE + EMP_INSERT + ( + pENAME IN VARCHAR, + pJOB IN VARCHAR, + pSAL IN FLOAT4, + pCOMM IN FLOAT4, + pDEPTNO IN INTEGER, + pMgr IN INTEGER + ) +AS +DECLARE + CURSOR TESTCUR IS SELECT MAX(EMPNO) FROM EMP; + MAX_EMPNO INTEGER := 10; +BEGIN + + OPEN TESTCUR; + FETCH TESTCUR INTO MAX_EMPNO; + INSERT INTO EMP(EMPNO,ENAME,JOB,SAL,COMM,DEPTNO,MGR) + VALUES(MAX_EMPNO+1,pENAME,pJOB,pSAL,pCOMM,pDEPTNO,pMgr); + CLOSE testcur; +END; + +``` + +When EDB Postgres Advanced Server validates the stored procedure, it echoes `CREATE PROCEDURE`. + +### Passing input values to a stored procedure + +Calling a stored procedure that contains parameters is similar to executing a stored procedure without parameters. The major difference is that, when calling a parameterized stored procedure, you must use the `EDBParameter` collection of the `EDBCommand` object. When the `EDBParameter` is added to the `EDBCommand` collection, properties such as `ParameterName`, `DbType`, `Direction`, `Size`, and `Value` are set. + +This example shows the process of executing a parameterized stored procedure from a C# script: + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +Save the sample code in a file named `storedProcInParam.aspx` in a web root directory. + +To invoke the sample code, enter the following in a browser: `http://localhost/storedProcInParam.aspx` + +In the example, the body of the `Page_Load` method declares and instantiates an `EDBConnection` object. The sample then creates an `EDBCommand` object with the properties needed to execute the stored procedure. + +The example then uses the `Add` method of the `EDBCommand Parameter` collection to add six input parameters. + +```cpp +EDBCommand cmdStoredProc = new EDBCommand +("emp_insert(:EmpName,:Job,:Salary,:Commission,:DeptNo,:Manager)",conn); +cmdStoredProc.CommandType = CommandType.StoredProcedure; +``` + +It assigns a value to each parameter before passing them to the `EMP_INSERT` stored procedure. + +The `Prepare()` method prepares the statement before calling the `ExecuteNonQuery()` method. + +The `ExecuteNonQuery` method of the `EDBCommand` object executes the stored procedure. After the stored procedure executes, a test record is inserted into the `emp` table, and the values inserted are displayed on the web page. + +## Example: Executing a stored procedure with IN, OUT, and INOUT parameters + +The previous example showed how to pass `IN` parameters to a stored procedure. The following examples show how to pass `IN` values and return `OUT` values from a stored procedure. + +### Creating the stored procedure + +The following stored procedure passes the department number and returns the corresponding location and department name. To create the sample procedure, invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Enter the following SPL code at the command line: + +```sql +CREATE OR REPLACE PROCEDURE + DEPT_SELECT + ( + pDEPTNO IN INTEGER, + pDNAME OUT VARCHAR, + pLOC OUT VARCHAR + ) +AS +DECLARE + CURSOR TESTCUR IS SELECT DNAME,LOC FROM DEPT; + REC RECORD; +BEGIN + + OPEN TESTCUR; + FETCH TESTCUR INTO REC; + + pDNAME := REC.DNAME; + pLOC := REC.LOC; + + CLOSE testcur; +END; +``` + +When EDB Postgres Advanced Server validates the stored procedure, it echoes `CREATE PROCEDURE`. + +### Receiving output values from a stored procedure + +When retrieving values from `OUT` parameters, you must explicitly specify the direction of those parameters as `Output`. You can retrieve the values from `Output` parameters in two ways: + +- Call the `ExecuteReader` method of the `EDBCommand` and explicitly loop through the returned `EDBDataReader`, searching for the values of `OUT` parameters. +- Call the `ExecuteNonQuery` method of `EDBCommand` and explicitly get the value of a declared `Output` parameter by calling that `EDBParameter` value property. + +In each method, you must declare each parameter, indicating the direction of the parameter (`ParameterDirection.Input`, `ParameterDirection.Output`, or `ParameterDirection.InputOutput`). Before invoking the procedure, you must provide a value for each `IN` and `INOUT` parameter. After the procedure returns, you can retrieve the `OUT` and `INOUT` parameter values from the `command.Parameters[]` array. + +This code shows using the `ExecuteReader` method to retrieve a result set: + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` + +This code shows using the `ExecuteNonQuery` method to retrieve a result set: + +```cpp +<% @ Page Language="C#" Debug="true"%> +<% @Import Namespace="EnterpriseDB.EDBClient" %> +<% @Import Namespace="System.Data" %> +<% @Import Namespace="System.Configuration" %> + +``` diff --git a/product_docs/docs/net_connector/8.0.5.1/12_using_advanced_queueing.mdx b/product_docs/docs/net_connector/8.0.5.1/12_using_advanced_queueing.mdx new file mode 100644 index 00000000000..a303b73cc25 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/12_using_advanced_queueing.mdx @@ -0,0 +1,492 @@ +--- +title: "Using advanced queueing" + +--- + + + +EDB Postgres Advanced Server advanced queueing provides message queueing and message processing for the EDB Postgres Advanced Server database. User-defined messages are stored in a queue. A collection of queues is stored in a queue table. Create a queue table before creating a queue that depends on it. + +On the server side, procedures in the `DBMS_AQADM` package create and manage message queues and queue tables. Use the `DBMS_AQ` package to add messages to or remove messages from a queue or register or unregister a PL/SQL callback procedure. For more information about `DBMS_AQ` and `DBMS_AQADM`, see [DBMS_AQ](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/02_dbms_aq/). + +On the client side, the application uses the EDB.NET driver to enqueue and dequeue messages. + +## Enqueueing or dequeueing a message + +For more information about using EDB Postgres Advanced Server's advanced queueing functionality, see [Built-in packages](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/). + +### Server-side setup + +To use advanced queueing functionality on your .NET application, you must first create a user-defined type, queue table, and queue, and then start the queue on the database server. Invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Use the following SPL commands at the command line. + +#### Creating a user-defined type + +To specify a RAW data type, create a user-defined type. This example shows creating a user-defined type named `myxml`: + +``` +CREATE TYPE myxml AS (value XML); +``` + +#### Creating the queue table + +A queue table can hold multiple queues with the same payload type. This example shows creating a table named `MSG_QUEUE_TABLE`: + +```Text +EXEC DBMS_AQADM.CREATE_QUEUE_TABLE + (queue_table => 'MSG_QUEUE_TABLE', + queue_payload_type => 'myxml', + comment => 'Message queue table'); +END; +``` + +#### Creating the queue + +This example shows creating a queue named `MSG_QUEUE` in the table `MSG_QUEUE_TABLE`: + +```Text +BEGIN +DBMS_AQADM.CREATE_QUEUE ( queue_name => 'MSG_QUEUE', queue_table => 'MSG_QUEUE_TABLE', comment => 'This queue contains pending messages.'); +END; +``` + +**Starting the queue** + +Once the queue is created, invoke the following SPL code at the command line to start a queue in the EDB database: + +```Text +BEGIN +DBMS_AQADM.START_QUEUE +(queue_name => 'MSG_QUEUE'); +END; +``` + +### Client-side example + +Once you've created a user-defined type, the queue table, and the queue, start the queue. Then, you can enqueue or dequeue a message using EDB .Net drivers. + +#### Enqueue a message + +To enqueue a message on your .NET application, you must: + +1. Import the `EnterpriseDB.EDBClient` namespace. +2. Pass the name of the queue and create the instance of the `EDBAQQueue`. +3. Create the enqueue message and define a payload. +4. Call the `queue.Enqueue` method. + +The following code shows using the `queue.Enqueue` method. + +!!! Note + This code creates the message and serializes it. This is example code and doesn't compile if copied as it is. You must serialize the message as XML. + +```csharp +using EnterpriseDB.EDBClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AQXml +{ + class MyXML + { + public string value { get; set; } + } + class Program + { + static void Main(string[] args) + { + int messagesToSend = 1; + if (args.Length > 0 && !string.IsNullOrEmpty(args[0])) + { + messagesToSend = int.Parse(args[0]); + } + for (int i = 0; i < 5; i++) + { + EnqueMsg("test message: " + i); + } + } + + private static EDBConnection GetConnection() + { + string connectionString = "Server=127.0.0.1;Host=127.0.0.1;Port=5444;User Id=enterprisedb;Password=test;Database=edb;Timeout=999"; + EDBConnection connection = new EDBConnection(connectionString); + connection.Open(); + return connection; + } + + + private static string ByteArrayToString(byte[] byteArray) + { + // Sanity check if it's null so we don't incur overhead of an exception + if (byteArray == null) + { + return string.Empty; + } + try + { + StringBuilder hex = new StringBuilder(byteArray.Length * 2); + foreach (byte b in byteArray) + { + hex.AppendFormat("{0:x2}", b); + } + + return hex.ToString().ToUpper(); + } + catch + { + return string.Empty; + } + } + + private static bool EnqueMsg(string msg) + { + EDBConnection con = GetConnection(); + using (EDBAQQueue queue = new EDBAQQueue("MSG_QUEUE", con)) + { + queue.MessageType = EDBAQMessageType.Xml; + EDBTransaction txn = queue.Connection.BeginTransaction(); + QueuedEntities.Message queuedMessage = new QueuedEntities.Message() { MessageText = msg }; + + try + { + string rootElementName = queuedMessage.GetType().Name; + if (rootElementName.IndexOf(".") != -1) + { + rootElementName = rootElementName.Split('.').Last(); + } + + string xml = new Utils.XmlFragmentSerializer().Serialize(queuedMessage); + EDBAQMessage queMsg = new EDBAQMessage(); + queMsg.Payload = new MyXML { value = xml }; + queue.MessageType = EDBAQMessageType.Udt; + queue.UdtTypeName = "myxml"; + EDBConnection.GlobalTypeMapper.MapComposite("myxml"); + con.ReloadTypes(); + queue.Enqueue(queMsg); + var messageId = ByteArrayToString((byte[])queMsg.MessageId); + Console.WriteLine("MessageID: " + messageId); + txn.Commit(); + queMsg = null; + xml = null; + rootElementName = null; + return true; + } + catch (Exception ex) + { + txn?.Rollback(); + Console.WriteLine("Failed to enqueue message."); + Console.WriteLine(ex.ToString()); + return false; + } + finally + { + queue?.Connection?.Dispose(); + } + } + } + + } +} +``` + +#### Dequeueing a message + +To dequeue a message on your .NET application, you must: + +1. Import the `EnterpriseDB.EDBClient` namespace. +2. Pass the name of the queue and create the instance of the `EDBAQQueue`. +3. Call the `queue.Dequeue` method. + +!!! Note + The following code creates the message and serializes it. This is example code and doesn't compile if copied as it is. You must serialize the message as XML. + +```csharp +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using EnterpriseDB.EDBClient; + +namespace DequeueXML +{ + class MyXML + { + public string value { get; set; } + } + class Program + { + static void Main(string[] args) + { + DequeMsg(); + } + + + private static EDBConnection GetConnection() + { + string connectionString = "Server=127.0.0.1;Host=127.0.0.1;Port=5444;User Id=enterprisedb;Password=test;Database=edb;Timeout=999"; + EDBConnection connection = new EDBConnection(connectionString); + connection.Open(); + return connection; + } + + + private static string ByteArrayToString(byte[] byteArray) + { + // Sanity check if it's null so we don't incur overhead of an exception + if (byteArray == null) + { + return string.Empty; + } + try + { + StringBuilder hex = new StringBuilder(byteArray.Length * 2); + foreach (byte b in byteArray) + { + hex.AppendFormat("{0:x2}", b); + } + + return hex.ToString().ToUpper(); + } + catch + { + return string.Empty; + } + } + public static void DequeMsg(int waitTime = 10) + { + EDBConnection con = GetConnection(); + using (EDBAQQueue queueListen = new EDBAQQueue("MSG_QUEUE", con)) + { + queueListen.UdtTypeName = "myxml"; + queueListen.DequeueOptions.Navigation = EDBAQNavigationMode.FIRST_MESSAGE; + queueListen.DequeueOptions.Visibility = EDBAQVisibility.ON_COMMIT; + queueListen.DequeueOptions.Wait = 1; + EDBTransaction txn = null; + + while (1 == 1) + { + + if (queueListen.Connection.State == System.Data.ConnectionState.Closed) + { + queueListen.Connection.Open(); + } + + string messageId = "Unknown"; + try + { + // the listen function is a blocking function. It will Wait the specified waitTime or until a + // message is received. + Console.WriteLine("Listening..."); + string v = queueListen.Listen(null, waitTime); + // If we are waiting for a message and we specify a Wait time, + // then if there are no more messages, we want to just bounce out. + if (waitTime > -1 && v == null) + { + Console.WriteLine("No message received during Wait period."); + Console.WriteLine(); + continue; + } + + // once we're here that means a message has been detected in the queue. Let's deal with it. + txn = queueListen.Connection.BeginTransaction(); + + Console.WriteLine("Attempting to dequeue message..."); + // dequeue the message + EDBAQMessage deqMsg; + try + { + deqMsg = queueListen.Dequeue(); + } + catch (Exception ex) + { + if (ex.Message.Contains("ORA-25228")) + { + Console.WriteLine("Message was not there. Another process must have picked it up."); + Console.WriteLine(); + txn.Rollback(); + continue; + } + else + { + throw; + } + } + + messageId = ByteArrayToString((byte[])deqMsg.MessageId); + if (deqMsg != null) + { + Console.WriteLine("Processing received message..."); + // process the message payload + MyXML obj = (MyXML) deqMsg.Payload; + + QueuedEntities.Message msg = new Utils.XmlFragmentSerializer().Deserialize(obj.value); + + Console.WriteLine("Received Message:"); + Console.WriteLine("MessageID: " + messageId); + Console.WriteLine("Message: " + msg.MessageText); + Console.WriteLine("Enqueue Time" + queueListen.MessageProperties.EnqueueTime); + + txn.Commit(); + + Console.WriteLine("Finished processing message"); + Console.WriteLine(); + + } + else + { + Console.WriteLine("Message was not dequeued."); + } + } + catch (Exception ex) + { + Console.WriteLine("Failed To dequeue or process the dequeued message."); + Console.WriteLine(ex.ToString()); + Console.WriteLine(); + if (txn != null) + { + txn.Rollback(); + if (txn != null) + { + txn.Dispose(); + } + } + } + } + } + + } + } +} +``` + +## EDBAQ classes + +The following EDBAQ classes are used in this application. + +### EDBAQDequeueMode + +The `EDBAQDequeueMode` class lists all the dequeuer modes available. + +| Value | Description | +| ------------- | ------------------------------------------------------------- | +| Browse | Reads the message without locking. | +| Locked | Reads and gets a write lock on the message. | +| Remove | Deletes the message after reading. This is the default value. | +| Remove_NoData | Confirms receipt of the message. | + +### EDBAQDequeueOptions + +The `EDBAQDequeueOptions` class lists the options available when dequeuing a message. + +| Property | Description | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| ConsumerName | The name of the consumer for which to dequeue the message. | +| DequeueMode | Set from `EDBAQDequeueMode`. It represents the locking behavior linked with the dequeue option. | +| Navigation | Set from `EDBAQNavigationMode`. It represents the position of the message to fetch. | +| Visibility | Set from `EDBAQVisibility`. It represents whether the new message is dequeued as part of the current transaction. | +| Wait | The wait time for a message as per the search criteria. | +| Msgid | The message identifier. | +| Correlation | The correlation identifier. | +| DeqCondition | The dequeuer condition. It's a Boolean expression. | +| Transformation | The transformation to apply before dequeuing the message. | +| DeliveryMode | The delivery mode of the dequeued message. | + +### EDBAQEnqueueOptions + +The `EDBAQEnqueueOptions` class lists the options available when enqueuing a message. + +| Property | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| Visibility | Set from `EDBAQVisibility`. It represents whether the new message is enqueued as part of the current transaction. | +| RelativeMsgid | The relative message identifier. | +| SequenceDeviation | The sequence when to dequeue the message. | +| Transformation | The transformation to apply before enqueuing the message. | +| DeliveryMode | The delivery mode of the enqueued message. | + +### EDBAQMessage + +The `EDBAQMessage` class lists a message to enqueue/dequeue. + +| Property | Description | +| ------------ | -------------------------------- | +| Payload | The actual message to queue. | +| MessageId | The ID of the queued message. | + +### EDBAQMessageProperties + +The `EDBAQMessageProperties` lists the message properties available. + +| Property | Description | +| ---------------- | --------------------------------------------------------------------------------------------- | +| Priority | The priority of the message. | +| Delay | The duration after which the message is available for dequeuing, in seconds. | +| Expiration | The duration for which the message is available for dequeuing, in seconds. | +| Correlation | The correlation identifier. | +| Attempts | The number of attempts taken to dequeue the message. | +| RecipientList | The recipients list that overthrows the default queue subscribers. | +| ExceptionQueue | The name of the queue to move the unprocessed messages to. | +| EnqueueTime | The time when the message was enqueued. | +| State | The state of the message while dequeued. | +| OriginalMsgid | The message identifier in the last queue. | +| TransactionGroup | The transaction group for the dequeued messages. | +| DeliveryMode | The delivery mode of the dequeued message. | + +### EDBAQMessageState + +The `EDBAQMessageState` class represents the state of the message during dequeue. + +| Value | Description | +| --------- | --------------------------------------------------------- | +| Expired | The message is moved to the exception queue. | +| Processed | The message is processed and kept. | +| Ready | The message is ready to be processed. | +| Waiting | The message is in waiting state. The delay isn't reached. | + +### EDBAQMessageType + +The `EDBAQMessageType` class represents the types for payload. + +| Value | Description | +| --------- | ------------------------------------------------------------------------------------- | +| Raw | The raw message type.

Note: Currently, this payload type isn't supported. | +| UDT | The user-defined type message. | +| XML | The XML type message.

Note: Currently, this payload type isn't supported. | + +### EDBAQNavigationMode + +The `EDBAQNavigationMode` class represents the different types of navigation modes available. + +| Value | Description | +| ---------------- | ------------------------------------------------------------------ | +| First_Message | Returns the first available message that matches the search terms. | +| Next_Message | Returns the next available message that matches the search items. | +| Next_Transaction | Returns the first message of next transaction group. | + +### EDBAQQueue + +The `EDBAQQueue` class represents a SQL statement to execute `DMBS_AQ` functionality on a PostgreSQL database. + +| Property | Description | +| ----------------- | --------------------------------------------------------------------------------------------- | +| Connection | The connection to use. | +| Name | The name of the queue. | +| MessageType | The message type that's enqueued/dequeued from this queue, for example `EDBAQMessageType.Udt`. | +| UdtTypeName | The user-defined type name of the message type. | +| EnqueueOptions | The enqueue options to use. | +| DequeuOptions | The dequeue options to use. | +| MessageProperties | The message properties to use. | + +### EDBAQVisibility + +The `EDBAQVisibility` class represents the visibility options available. + +| Value | Description | +| --------- | ----------------------------------------------------------- | +| Immediate | The enqueue/dequeue isn't part of the ongoing transaction. | +| On_Commit | The enqueue/dequeue is part of the current transaction. | + +!!! Note + - To review the default options for these parameters, see [DBMS_AQ](../../epas/11/epas_compat_bip_guide/03_built-in_packages/02_dbms_aq/). + - EDB advanced queueing functionality uses user-defined types for calling enqueue/dequeue operations. `Server Compatibility Mode=NoTypeLoading` can't be used with advanced queueing because `NoTypeLoading` doesn't load any user-defined types. diff --git a/product_docs/docs/net_connector/8.0.5.1/13_using_a_ref_cursor_in_a_net_application.mdx b/product_docs/docs/net_connector/8.0.5.1/13_using_a_ref_cursor_in_a_net_application.mdx new file mode 100644 index 00000000000..eee3876bfab --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/13_using_a_ref_cursor_in_a_net_application.mdx @@ -0,0 +1,104 @@ +--- +title: "Using a ref cursor in a .NET application" + +--- + + + +A `ref cursor` is a cursor variable that contains a pointer to a query result set. The result set is determined by executing the `OPEN FOR` statement using the cursor variable. A cursor variable isn't tied to a particular query like a static cursor. You can open the same cursor variable a number of times with the `OPEN FOR` statement containing different queries each time. A new result set is created for that query and made available by way of the cursor variable. You can declare a cursor variable in two ways: + +- Use the `SYS_REFCURSOR` built-in data type to declare a weakly typed ref cursor. +- Define a strongly typed ref cursor that declares a variable of that type. + +`SYS_REFCURSOR` is a ref cursor type that allows any result set to be associated with it. This is known as a weakly typed ref cursor. The following example is a declaration of a weakly typed ref cursor: + +``` + name SYS_REFCURSOR`; +``` + +Following is an example of a strongly typed ref cursor: + +``` +TYPE IS REF CURSOR RETURN emp%ROWTYPE`; +``` + +## Creating the stored procedure + +This sample code creates a stored procedure called `refcur_inout_callee`. It specifies the data type of the ref cursor being passed as an OUT parameter. To create the sample procedure, invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Enter the following SPL code at the command line: + +```sql +CREATE OR REPLACE PROCEDURE + refcur_inout_callee(v_refcur OUT SYS_REFCURSOR) +IS +BEGIN + OPEN v_refcur FOR SELECT ename FROM emp; +END; +``` + +This C# code uses the stored procedure to retrieve employee names from the `emp` table: + +```cpp +using System; +using System.Data; +using EnterpriseDB.EDBClient; +using System.Configuration; +namespace EDBRefCursor +{ + class EmpRefcursor + { + [STAThread] + static void Main(string[] args) + { + var strConnectionString = + ConfigurationManager.AppSettings["DB_CONN_STRING"]; + try + { + await using var dataSource = EDBDataSource.Create(ConnectionString); + var conn = await dataSource.OpenConnectionAsync(); + await using var tran = await connection.BeginTransactionAsync(); + using var command = new EDBCommand("refcur_inout_callee", conn); + command.CommandType = CommandType.StoredProcedure; + command.Transaction = tran; + command.Parameters.Add(new EDBParameter("refCursor", + EDBTypes.EDBDbType.Refcursor, 10, "refCursor", + ParameterDirection.Output, false, 2, 2, + System.Data.DataRowVersion.Current, null)); + await command.PrepareAsync(); + command.Parameters[0].Value = null; + await command.ExecuteNonQueryAsync(); + var cursorName = command.Parameters[0].Value.ToString(); + command.CommandText = "fetch all in \"" + cursorName + "\""; + command.CommandType = CommandType.Text; + await using var reader = + await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess); + var fc = reader.FieldCount; + while (await reader.ReadAsync()) + { + for (int i = 0; i < fc; i++) + { + Console.WriteLine(reader.GetString(i)); + } + } + await reader.CloseAsync(); + await tran.CommitAsync(); + await conn.CloseAsync(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message.ToString()); + } + } + } +} +``` + +This .NET code snippet displays the result on the console: + +```cpp +for(int i = 0;i < fc; i++) +{ + Console.WriteLine(reader.GetString(i)); +} +``` + +You must bind the `EDBDbType.RefCursor` type in `EDBParameter()` if you're using a ref cursor parameter. diff --git a/product_docs/docs/net_connector/8.0.5.1/14_using_plugins.mdx b/product_docs/docs/net_connector/8.0.5.1/14_using_plugins.mdx new file mode 100644 index 00000000000..9e8a3b1389e --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/14_using_plugins.mdx @@ -0,0 +1,72 @@ +--- +title: "Using plugins" + +--- + + + +EDB .Net driver plugins support the enhanced capabilities for different data types that are otherwise not available in .Net. The different plugins available support: + +- GeoJSON +- Json.NET +- NetTopologySuite +- NodaTime + +The plugins support the use of spatial, data/time, and JSON types. The following are the supported frameworks and data provider installation path for these plugins. + +## GeoJSON + +If you're using the GeoJSON plugin on .NET Standard 2.0, the data provider installation paths are: + +- `C:\Program Files\edb\dotnet\plugins\GeoJSON\netstandard2.0` +- `C:\Program Files\edb\dotnet\plugins\GeoJSON\net472` +- `C:\Program Files\edb\dotnet\plugins\GeoJSON\net48` +- `C:\Program Files\edb\dotnet\plugins\GeoJSON\net481` + +The following shared library files are required: + +- `EnterpriseDB.EDBClient.GeoJSON.dll` + +For detailed information about using the GeoJSON plugin, see the [Npgsql documentation](http://www.npgsql.org/doc/types/geojson.html). + +## Json.NET + +If you're using the Json.NET plugin on .NET Standard 2.0, the data provider installation paths are: +- `C:\Program Files\edb\dotnet\plugins\Json.NET\netstandard2.0` +- `C:\Program Files\edb\dotnet\plugins\Json.NET\net472` +- `C:\Program Files\edb\dotnet\plugins\Json.NET\net48` +- `C:\Program Files\edb\dotnet\plugins\Json.NET\net481` + +The following shared library files are required: + +- `EnterpriseDB.EDBClient.Json.NET.dll` + +For detailed information about using the Json.NET plugin, see the [Npgsql documentation](http://www.npgsql.org/doc/types/jsonnet.html). + +## NetTopologySuite + +If you're using the NetTopologySuite plugin on .Net Standard 2.0, the data provider installation paths are: +- `C:\Program Files\edb\dotnet\plugins\NetTopologySuite\netstandard2.0` +- `C:\Program Files\edb\dotnet\plugins\NetTopologySuite\net472` +- `C:\Program Files\edb\dotnet\plugins\NetTopologySuite\net48` +- `C:\Program Files\edb\dotnet\plugins\NetTopologySuite\net481` + +The following shared library files are required: + +- `EnterpriseDB.EDBClient.NetTopologySuite.dll` + +For detailed information about using the NetTopologySuite type plugin, see the [Npgsql documentation](http://www.npgsql.org/doc/types/nts.html). + +## NodaTime + +If you're using the NodaTime plugin on .Net Standard 2.0, the data provider installation paths are: +- `C:\Program Files\edb\dotnet\plugins\NodaTime\netstandard2.0` +- `C:\Program Files\edb\dotnet\plugins\NodaTime\net472` +- `C:\Program Files\edb\dotnet\plugins\NodaTime\net48` +- `C:\Program Files\edb\dotnet\plugins\NodaTime\net481` + +The following shared library files are required: + +- `EnterpriseDB.EDBClient.NodaTime.dll` + +For detailed information about using the NodaTime plugin, see the [Npgsql documentation](http://www.npgsql.org/doc/types/nodatime.html). diff --git a/product_docs/docs/net_connector/8.0.5.1/15_using_object_types.mdx b/product_docs/docs/net_connector/8.0.5.1/15_using_object_types.mdx new file mode 100644 index 00000000000..d44f575cf7a --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/15_using_object_types.mdx @@ -0,0 +1,181 @@ +--- +title: "Using object types in .NET" + +--- + + + +The SQL `CREATE TYPE` command creates a user-defined object type, which is stored in the EDB Postgres Advanced Server database. You can then reference these user-defined types in SPL procedures, SPL functions, and .NET programs. + +Create the basic object type with the `CREATE TYPE AS OBJECT` command. Optionally, use the `CREATE TYPE BODY` command. + +## Using an object type + +To use an object type, you must first create the object type in the EDB Postgres Advanced Server database. Object type `addr_object_type` defines the attributes of an address: + +```sql +CREATE OR REPLACE TYPE addr_object_type AS OBJECT +( + street VARCHAR2(30), + city VARCHAR2(20), + state CHAR(2), + zip NUMBER(5) +); +``` + +Object type `emp_obj_typ` defines the attributes of an employee. One of these attributes is object type `ADDR_OBJECT_TYPE`, as previously described. The object type body contains a method that displays the employee information: + +```sql +CREATE OR REPLACE TYPE emp_obj_typ AS OBJECT +( + empno NUMBER(4), + ename VARCHAR2(20), + addr ADDR_OBJECT_TYPE, + MEMBER PROCEDURE display_emp(SELF IN OUT emp_obj_typ) +); + +CREATE OR REPLACE TYPE BODY emp_obj_typ AS + MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_typ) + IS + BEGIN + DBMS_OUTPUT.PUT_LINE('Employee No : ' || SELF.empno); + DBMS_OUTPUT.PUT_LINE('Name : ' || SELF.ename); + DBMS_OUTPUT.PUT_LINE('Street : ' || SELF.addr.street); + DBMS_OUTPUT.PUT_LINE('City/State/Zip: ' || SELF.addr.city || ', ' || + SELF.addr.state || ' ' || LPAD(SELF.addr.zip,5,'0')); + END; +END; +``` + +This example is a complete .NET program that uses these user-defined object types: + +```csharp +using EnterpriseDB.EDBClient; +using System.Data.Common; +namespace TypesTest +{ + internal class Program + { + static async Task Main(string[] args) + { + var connString = "Server=localhost;Port=5444;database=edb;User ID=enterprisedb;password=edb;"; + var dataSourceBuilder = new EDBDataSourceBuilder(connString); + dataSourceBuilder.MapComposite("enterprisedb.addr_object_type"); + dataSourceBuilder.MapComposite("enterprisedb.emp_obj_typ"); + await using var dataSource = dataSourceBuilder.Build(); + await using var conn = await dataSource.OpenConnectionAsync(); + try + { + var address = new addr_object_type() + { + street = "123 MAIN STREET", + city = "EDISON", + state = "NJ", + zip = 8817 + }; + var emp = new emp_obj_typ() + { + empno = 9001, + ename = "JONES", + addr = address + }; + await using (var cmd = new EDBCommand("emp_obj_typ.display_emp", conn)) + { + cmd.CommandType = System.Data.CommandType.StoredProcedure; + EDBCommandBuilder.DeriveParameters(cmd); + cmd.Parameters[0].Value = emp; + cmd.Prepare(); + cmd.ExecuteNonQuery(); + var empOut = (emp_obj_typ?)cmd.Parameters[0].Value; + Console.WriteLine("Emp No: " + empOut.empno); + Console.WriteLine("Emp Name: " + empOut.ename); + Console.WriteLine("Emp Address Street: " + empOut.addr.street); + Console.WriteLine("Emp Address City: " + empOut.addr.city); + Console.WriteLine("Emp Address State: " + empOut.addr.state); + Console.WriteLine("Emp Address Zip: " + empOut.addr.zip); + Console.WriteLine("Emp No: " + empOut.empno); + } + } + catch (EDBException exp) + { + Console.WriteLine(exp.Message.ToString()); + } + finally + { + conn.Close(); + } + } + } +public class addr_object_type + { + public string? street; + public string? city; + public string? state; + public decimal zip; + } + public class emp_obj_typ + { + public decimal empno; + public string? ename; + public addr_object_type? addr; + } +} +``` + +The following .NET types are defined to map to the types in EDB Postgres Advanced Server: + +```csharp +public class addr_object_type +{ +public string? street; +public string? city; +public string? state; +public decimal zip; +} + +public class emp_obj_typ +{ + public decimal empno; + public string? ename; + public addr_object_type? addr; +} +``` + +A call to `EDBDataSourceBuilder.MapComposite` maps the .NET type to the EDB Postgres Advanced Server types: + +```csharp +dataSourceBuilder.MapComposite("enterprisedb.addr_object_type"); +dataSourceBuilder.MapComposite("enterprisedb.emp_obj_typ"); +``` + +A call to `EDBCommandBuilder.DeriveParameters()` gets parameter information for a stored procedure. This allows you to just set the parameter values and call the stored procedure: + +```csharp +EDBCommandBuilder.DeriveParameters(cmd); +``` + +Set the value of the parameter by creating an object of the .NET type and assigning it to the `Value` property of the parameter: + +```csharp +addr_object_type address = new addr_object_type() +{ + street = "123 MAIN STREET", + city = "EDISON", + state = "NJ", + zip = 8817 +}; + +emp_obj_typ emp = new emp_obj_typ() +{ + empno = 9001, + ename = "JONES", + addr = address +}; +cmd.Parameters[0].Value = emp; +``` + +A call to `cmd.ExecuteNonQuery()` executes the call to the `display_emp()` method: + +```csharp +cmd.ExecuteNonQuery(); +``` diff --git a/product_docs/docs/net_connector/8.0.5.1/16_scram_compatibility.mdx b/product_docs/docs/net_connector/8.0.5.1/16_scram_compatibility.mdx new file mode 100644 index 00000000000..96388c7a6b6 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/16_scram_compatibility.mdx @@ -0,0 +1,10 @@ +--- +title: "Scram compatibility" +legacyRedirects: + - "/edb-docs/d/edb-postgres-net-connector/user-guides/net-guide/4.1.6.1/security_and_encryption.html" + +--- + + + +The EDB .NET driver provides SCRAM-SHA-256 support for EDB Postgres Advanced Server version 10 and later. This support is available in EDB .NET 4.0.2.1 release and later. diff --git a/product_docs/docs/net_connector/8.0.5.1/17_advanced_server_net_connector_logging.mdx b/product_docs/docs/net_connector/8.0.5.1/17_advanced_server_net_connector_logging.mdx new file mode 100644 index 00000000000..fb5664d14cf --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/17_advanced_server_net_connector_logging.mdx @@ -0,0 +1,82 @@ +--- +title: "EDB .NET Connector logging" + +--- + + + +EDB .NET Connector supports the use of logging to help resolve issues with the .NET Connector when used in your application. EDB .NET Connector supports logging using the standard .NET `Microsoft.Extensions.Logging` package. For more information about logging in .Net, see [Logging in C# and .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line) in the Microsoft documentation. + +!!! Note + For versions earlier than 7.x, EDB .NET Connector had its own, custom logging API. + +## Console logging provider + +The .NET logging API works with a variety of built-in and third-party logging providers. The console logging provider logs output to the console. + +### Console logging with EDBDataSource + +Create a `Microsoft.Extensions.Logging.LoggerFactory` and configure an `EDBDataSource` with it. Any use of connections opened through this data source log using this logger factory. + +```csharp +var loggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole()); + +var dataSourceBuilder = new EDBDataSourceBuilder(connectionString); +dataSourceBuilder.UseLoggerFactory(loggerFactory); +await using var dataSource = dataSourceBuilder.Build(); + +await using var connection = await dataSource.OpenConnectionAsync(); +await using var command = new EDBCommand("SELECT 1", connection); +_ = await command.ExecuteScalarAsync(); +``` + +### Console logging without EDBDataSource + +Create a `Microsoft.Extensions.Logging.LoggerFactory` and configure EDB .NET Connector's logger factory globally using `EDBLoggingConfiguration.InitializeLogging`. Configure it at the start of your program, before using any other EDB .NET Connector API. + +```csharp +var loggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole()); +EDBLoggingConfiguration.InitializeLogging(loggerFactory); + +await using var conn = new EDBConnection(connectionString); +await conn.OpenAsync(); +await using var command = new EDBCommand("SELECT 1", conn); +_ = await command.ExecuteScalarAsync(); +``` + +## Log levels + +The following log levels are available: + +- Trace +- Debug +- Information +- Warning +- Error +- Fatal + +This example shows how to change the log level to `Trace`: + +```csharp +var loggerFactory = LoggerFactory.Create(builder => builder +.SetMinimumLevel(LogLevel.Trace +.AddSimpleConsole() +); +``` + +## Formatting the log output + +This example shows how to format your log output. Create a `LoggerFactory` to restrict each log message to a single line and add a date and time to the log: + +```csharp +var loggerFactory = LoggerFactory.Create(builder => +builder +.SetMinimumLevel(LogLevel.Trace) +.AddSimpleConsole( + options => + { + options.SingleLine = true; + options.TimestampFormat = "yyyy/MM/dd HH:mm:ss "; + } + )); +``` \ No newline at end of file diff --git a/product_docs/docs/net_connector/8.0.5.1/18_api_reference.mdx b/product_docs/docs/net_connector/8.0.5.1/18_api_reference.mdx new file mode 100644 index 00000000000..53050c37952 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/18_api_reference.mdx @@ -0,0 +1,13 @@ +--- +title: "API reference" + +--- + + + +For information about using the API, see the [Npgsql documentation](http://www.npgsql.org/doc/api/Npgsql.html). + +Usage notes: + +- When using the API, replace references to `Npgsql` with `EnterpriseDB.EDBClient`. +- When referring to classes, replace `Npgsql` with `EDB`. For example, use the `EDBBinaryExporter` class instead of the `NpgsqlBinaryExporter` class. diff --git a/product_docs/docs/net_connector/8.0.5.1/images/connection_opened_successfully.png b/product_docs/docs/net_connector/8.0.5.1/images/connection_opened_successfully.png new file mode 100755 index 00000000000..bab12126d20 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/connection_opened_successfully.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:537e7edecce3882b794110e0ffc644a51cab69ba2c7e7f82a3e99d32c4b4ba65 +size 22683 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/dialog.png b/product_docs/docs/net_connector/8.0.5.1/images/dialog.png new file mode 100755 index 00000000000..19cba54d1f9 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/dialog.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f922e6cd4e43927708b5f460f5389a5b3a41dd70f3a5394723e6aee7d710f1ae +size 9048 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_complete.png b/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_complete.png new file mode 100755 index 00000000000..332ae795899 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_complete.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0983f216ce071f57f7e758980c3f966caded4312412905a6aba66efa362fdb13 +size 272137 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_dialog.png b/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_dialog.png new file mode 100755 index 00000000000..b465d536032 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_dialog.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:994a725f061f1b51fd92ccc2df5abd9066a1cf4ea7600611ae57ebc6cc59af20 +size 51144 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_wizard.png b/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_wizard.png new file mode 100755 index 00000000000..29c9a7f99f9 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/dotnet_installation_wizard.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efe8029105db01662005a349a7b59c87b6f7dce3017990a197e3b9b681392860 +size 227235 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/ready_to_install.png b/product_docs/docs/net_connector/8.0.5.1/images/ready_to_install.png new file mode 100755 index 00000000000..59e44d96bc5 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/ready_to_install.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91b18bef7b78a6dae7d6b664e2bccfbfdb4248dbd034cb59e2c6a35ada7da49c +size 44080 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/selecting_the_connectors_installer.png b/product_docs/docs/net_connector/8.0.5.1/images/selecting_the_connectors_installer.png new file mode 100755 index 00000000000..432e4473c09 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/selecting_the_connectors_installer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d939c7e6604025f82be47969d69e6acc63ab5a48a0af4341e42efe0156b42778 +size 97808 diff --git a/product_docs/docs/net_connector/8.0.5.1/images/starting_stackbuilder_plus.png b/product_docs/docs/net_connector/8.0.5.1/images/starting_stackbuilder_plus.png new file mode 100755 index 00000000000..11665300652 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/images/starting_stackbuilder_plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce6bcefb865ca14239fb7e0e2ac5149ed56251cfbc5153869070d039f70857c6 +size 91989 diff --git a/product_docs/docs/net_connector/8.0.5.1/index.mdx b/product_docs/docs/net_connector/8.0.5.1/index.mdx new file mode 100644 index 00000000000..01dd6268d09 --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/index.mdx @@ -0,0 +1,39 @@ +--- +title: "EDB .NET Connector" +directoryDefaults: + description: "EDB .NET Connector version 8.0.5.1 documentation and release notes." +navigation: + - 01_release_notes + - 02_requirements_overview + - 03_the_advanced_server_net_connector_overview + - 04_installing_and_configuring_the_net_connector + - 05_using_the_net_connector + - 06_opening_a_database_connection + - 07_retrieving_database_records + - 08_parameterized_queries + - 09_inserting_records_in_a_database + - 10_deleting_records_in_a_database + - 11_using_spl_stored_procedures_in_your_net_application + - 12_using_advanced_queueing + - 13_using_a_ref_cursor_in_a_net_application + - 14_using_plugins + - 15_using_object_types + - using_nested_table_types + - 16_scram_compatibility + - 17_advanced_server_net_connector_logging + - 18_api_reference +--- + +The EDB .NET Connector distributed with EDB Postgres Advanced Server provides connectivity between a .NET client application and an EDB Postgres Advanced Server database server. You can: + +- Connect to an instance of EDB Postgres Advanced Server. +- Retrieve information from an EDB Postgres Advanced Server database. +- Update information stored on an EDB Postgres Advanced Server database. + +To understand these examples, you need a solid working knowledge of C# and .NET. The EDB .NET Connector functionality is built on the core functionality of the Npgsql open source project. For details, see the [Npgsql User Guide](http://www.npgsql.org/doc/index.html). + +
+ +release_notes requirements_overview the_advanced_server_net_connector_overview installing_and_configuring_the_net_connector using_the_net_connector opening_a_database_connection retrieving_database_records parameterized_queries inserting_records_in_a_database deleting_records_in_a_database using_spl_stored_procedures_in_your_net_application using_advanced_queueing using_a_ref_cursor_in_a_net_application using_plugins using_object_types scram_compatibility advanced_server_net_connector_logging api_reference conclusion + +
diff --git a/product_docs/docs/net_connector/8.0.5.1/using_nested_table_types.mdx b/product_docs/docs/net_connector/8.0.5.1/using_nested_table_types.mdx new file mode 100644 index 00000000000..4bc1f1a348b --- /dev/null +++ b/product_docs/docs/net_connector/8.0.5.1/using_nested_table_types.mdx @@ -0,0 +1,178 @@ +--- +title: "Using nested tables" + +--- + +EDB Postgres Advanced Server supports nested table collection types created with `CREATE TYPE ... AS TABLE OF` statements. The EDB .NET Connector supports output parameters declared as nested tables out of the box, whether free-standing types or declared inside packages. + +## Nested table types mapping + +Nested table types are mapped to `List`s in C#, as it is preferred over `ArrayList`. These lists contain as many elements as the nested table type's rows. The nested table items are translated to be compatible with the C# application using the following rules: + +- The connector resolves all nested table rows into a `List` in C# while maintaining and converting each column's underlying type. For example, a `[text1, text2, num1]` row will be resolved as a `[string, string, decimal]` item in the list. + +- If the nested type `IS TABLE OF` a domain type (int, varchar, decimal, etc.), all the rows will be their C# counterpart according to the [Supported Types and their Mappings](https://www.npgsql.org/doc/types/basic.html#read-mappings). + +- If the nested type `IS TABLE OF` a record or composite type **not mapped** to a C# class, all rows become a nested List containing as many elements as the record or composite fields, with proper type translation. + +- If the nested type `IS TABLE OF` a record or composite type **mapped** to a C# class (for example, `MyComposite`), all rows will be `MyComposite` instances. + +## Example: Retrieving nested table output parameter + +This program: + +- Creates a package with a nested `emp_tbl_typ` table type of `emp_rec_typ`. This package has a stored procedure that fills the nested table output parameter. + +- Maps the nested table type to a C# class via `MapComposite<>`. + +- Executes and displays the results. + +!!!note + Always provide type names in lowercase. +!!! + +### Program example + +Create an empty console program and paste the following code. + +```csharp +internal static class Program +{ + const string ConnectionString = "your_connection_string"; + + // Composite type, will be mapped to the nested table type + // This will work if field types are convertible from database types + public class Employee + { + [PgName("empno")] + public decimal Number; + [PgName("ename")] + public string? Name; + } + + public static void Sample_NestedTableTypes(string ConnectionString) + { + var dataSourceBuilder = new EDBDataSourceBuilder(ConnectionString); + dataSourceBuilder.MapComposite("pkgextendtest.emp_rec_typ"); + + using (var dataSource = dataSourceBuilder.Build()) + { + using (var connection = dataSource.OpenConnection()) + { + + try + { + CreatePackage(connection); + + var commandText = "pkgExtendTest.nestedTableExtendTest"; + var cstmt = new EDBCommand(commandText, connection); + cstmt.CommandType = CommandType.StoredProcedure; + + var tableOfParam = cstmt.Parameters.Add(new EDBParameter() + { + Direction = ParameterDirection.Output, + DataTypeName = "pkgextendtest.emp_tbl_typ" + }); + + cstmt.Prepare(); + cstmt.ExecuteNonQuery(); + + List? employees = tableOfParam.Value as List; + if (employees == null) + { + Console.WriteLine($"No employee found"); + return; + } + + foreach (var employeeRecord in employees) + { + var employee = employeeRecord as Employee; + if (employee != null) + { + Console.WriteLine($"Employee {employee.Number}: {employee.Name}"); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + finally + { + Cleanup(connection); + } + } + } + } + + // helper methods to create package and cleaning up + static void CreatePackage(EDBConnection connection) + { + var createPackage = +" CREATE OR REPLACE PACKAGE pkgExtendTest IS \n" + +" TYPE emp_rec_typ IS RECORD ( \n" + +" empno NUMBER(4), \n" + +" ename VARCHAR2(10) \n" + +" ); \n" + +" TYPE emp_tbl_typ IS TABLE OF emp_rec_typ; \n" + +" PROCEDURE nestedTableExtendTest(emp_tbl OUT emp_tbl_typ); \n" + +" END pkgExtendTest; \n"; + using (var com = new EDBCommand(createPackage, connection) { CommandType = CommandType.Text }) + { + com.ExecuteNonQuery(); + } + + var createPackageBody = +" CREATE OR REPLACE PACKAGE BODY pkgExtendTest IS \n" + +" PROCEDURE nestedTableExtendTest(emp_tbl OUT emp_tbl_typ) IS \n" + +" DECLARE \n" + +" CURSOR emp_cur IS SELECT empno, ename FROM emp WHERE ROWNUM <= 10 order by empno; \n" + +" i INTEGER := 0; \n" + +" BEGIN \n" + +" emp_tbl := emp_tbl_typ(); \n" + +" FOR r_emp IN emp_cur LOOP \n" + +" i := i + 1; \n" + +" emp_tbl.EXTEND; \n" + +" emp_tbl(i) := r_emp; \n" + +" END LOOP; \n" + +" END nestedTableExtendTest; \n" + +" END pkgExtendTest; \n"; + using (var com = new EDBCommand(createPackageBody, connection) { CommandType = CommandType.Text }) + { + com.ExecuteNonQuery(); + } + + connection.ReloadTypes(); + } + + static void Cleanup(EDBConnection connection) + { + var dropPackageBody = "DROP PACKAGE BODY pkgExtendTest"; + var dropPackage = "DROP PACKAGE pkgExtendTest"; + + using (var com = new EDBCommand(dropPackageBody, connection) { CommandType = CommandType.Text }) + { + com.ExecuteNonQuery(); + } + using (var com = new EDBCommand(dropPackage, connection) { CommandType = CommandType.Text }) + { + com.ExecuteNonQuery(); + } + } +} +``` + +The output should look like this: + +```text +Employee 7499: ALLEN +Employee 7521: WARD +Employee 7566: JONES +Employee 7654: MARTIN +Employee 7698: BLAKE +Employee 7782: CLARK +Employee 7788: SCOTT +Employee 7839: KING +Employee 7844: TURNER +Employee 7876: ADAMS +``` diff --git a/product_docs/docs/pem/9/considerations/licensing.mdx b/product_docs/docs/pem/9/considerations/licensing.mdx index 62b734050f9..05f696ddcb6 100644 --- a/product_docs/docs/pem/9/considerations/licensing.mdx +++ b/product_docs/docs/pem/9/considerations/licensing.mdx @@ -15,45 +15,47 @@ instances generally incurs no additional license costs. To use PEM, you must have an EDB Standard or Enterprise subscription. -Any Postgres servers you monitor using PEM (whether by installing the -PEM Agent locally, through Remote Monitoring, or by making a client -connection from the PEM web application) must be covered by an EDB -Standard or Enterprise subscription. +Any Postgres servers you monitor using PEM must be covered by an EDB +Standard or Enterprise subscription. This is true whether you're installing the +PEM agent locally, through remote monitoring, or by making a client +connection from the PEM web application. -Non-Postgres servers that do not otherwise consume cores (for example +Non-Postgres servers that don't otherwise consume cores (for example PGD Proxy nodes or machines running Barman) may be monitored by PEM. No additional cores are consumed by monitoring such servers with PEM. -The Postgres instance used as the PEM backend does not consume cores +The Postgres instance used as the PEM backend doesn't consume cores from your subscription. Likewise, no cores are consumed by any other PEM components. All these components are covered by your support agreement. ## Examples -### Adding PEM to a fully-supported environment -A customer with an Enterprise subscription for 32 cores has 8 x 4-core -servers running EDB Postgres Advanced Server (EPAS), thereby fully -consuming their 32 cores. This customer may install PEM on a fifth -server and use it to monitor their 8 EPAS servers. This requires no -change to their subscription as the PEM server does not consume cores -and the monitored EPAS instances are already fully covered. +### Adding PEM to a fully supported environment + +Suppose a customer with an Enterprise subscription for 32 cores has 8 x 4-core +servers running EDB Postgres Advanced Server, thereby fully +consuming their 32 cores. This customer can install PEM on a fifth +server and use it to monitor their 8 EDB Postgres Advanced Server servers. This configuration requires no +change to their subscription, as the PEM server doesn't consume cores, +and the monitored EDB Postgres Advanced Server instances are already fully covered. Likewise, if this customer added a Barman server and connected it to PEM for monitoring, they would consume no additional cores. ### Adding unsupported servers to PEM -A customer with a Standard subscription for 36 cores has PEM and 6 x -6-core servers running PostgreSQL covered by EDB support - thereby -consuming their 36 cores as in the example above. -The customer also has 10 x 2-core PostgreSQL servers that are not +Suppose a customer with a Standard subscription for 36 cores has PEM and 6 x +6-core servers running PostgreSQL covered by EDB support, thereby +consuming their 36 cores, as in the previous example. + +The customer also has 10 x 2-core PostgreSQL servers that aren't covered by any EDB subscription. These servers must not be monitored by -PEM as they are not covered by a Standard or Enterprise subscription. If -the customer wishes to monitor these servers they must add a further 20 +PEM, as they aren't covered by a Standard or Enterprise subscription. If +the customer wants to monitor these servers, they must add 20 more cores to their subscription. !!! Note -An EDB Community 360 subscription for the additional 20 cores is not +An EDB Community 360 subscription for the additional 20 cores isn't sufficient. Servers monitored by PEM must be covered by Standard or Enterprise. !!! diff --git a/product_docs/docs/pgd/5.6/nodes/subscriber_only/optimizing-so.mdx b/product_docs/docs/pgd/5.6/nodes/subscriber_only/optimizing-so.mdx index 95ecfaf21e5..7ddaa7c19dc 100644 --- a/product_docs/docs/pgd/5.6/nodes/subscriber_only/optimizing-so.mdx +++ b/product_docs/docs/pgd/5.6/nodes/subscriber_only/optimizing-so.mdx @@ -1,65 +1,67 @@ --- title: Optimizing subscriber-only groups navTitle: Optimizing -description: 'Optimizing subscriber-only groups in EDB Postgres Distributed' +description: 'Optimizing subscriber-only groups in EDB Postgres Distributed.' --- With PGD 5.6 and later, it's possible to optimize the topology of [subscriber-only groups](overview). -In this optimized topology, a small number of fully active nodes, the write leaders of the data groups, replicate changes to the group leaders of subscriber-only groups, these group leaders then replicate changes to the other members of its subscriber-only group. +In this optimized topology, a small number of fully active nodes—the write leaders of the data groups—replicate changes to the group leaders of subscriber-only groups. These group leaders then replicate changes to the other members of its subscriber-only group. ## Requirements for the optimized topology You can't enable this model if a cluster has any of the following: -* Data-nodes which are directly members of the top-level group. -* No data-node sub-groups. -* No data-node sub-groups with proxy routing enabled. +* Data nodes that are directly members of the top-level group +* No data-node subgroups +* No data-node subgroups with proxy routing enabled -If this is the case, the nodes in a subscriber only groups automatically revert to the full mesh topology. +If any of these are the case, the nodes in subscriber-only groups revert to the full mesh topology. -To get the benefit of the new SO group and node replication, you must have your data-nodes in subgroups, with proxy routing enabled on the sub groups. +To get the benefit of the new SO group and node replication, you must have your data nodes in subgroups, with proxy routing enabled on the subgroups. ## How the optimized topology works -For clusters using groups for their data nodes, subscriber only groups can use a more efficient model which uses a subscriber-only group leader, similar to a write leader in PGD Proxies. +For clusters using groups for their data nodes, subscriber-only groups can use a more efficient model. This model uses subscriber-only group leaders, similar to write leaders in PGD proxies. Each subscriber-only group uses that group leader to replicate changes to other subscriber-only nodes in its group. The group leader acts as a replication proxy for incoming changes. -The write leader nodes in other non-subscriber-only groups replicate changes to the group leader of the subscriber-only group. Other nodes only replicate within their data groups, both within their own group and in other data groups. +The write leader nodes in data groups replicate changes to the group leaders of the subscriber-only groups. Other nodes in the data groups only replicate with nodes in their data group and with data nodes in other data groups. They do not directly replicate their changes to the subscriber-only groups. ## Subscriber-only group leaders With PGD 5.6 and later, each subscriber-only group gets assigned a group leader of its own. This is because subscriber-only groups don't have a group Raft consensus mechanism of their own. -Instead, the cluster’s top level group uses its Raft consensus mechanism to handle selection of each subscriber-only group’s group leader. -This group leader selection is on by default on PGD 5.6, regardless of the topology optimization settings. +Instead, the cluster’s top-level group uses its Raft consensus mechanism to handle selecting each subscriber-only group’s group leader. +This group leader selection is on by default in PGD 5.6, regardless of the topology optimization settings. -Group leaders in subscriber-only groups are regularly tested for connectivity and if unavailable, the voting nodes of top-level group select a new subscriber-only node from the subscriber-only group to become group leader. -The new group leader is then selected. +Group leaders in subscriber-only groups are regularly tested for connectivity and, if unavailable, the voting nodes of top-level group select a new subscriber-only node from the subscriber-only group to become group leader. +The new group leader is then selected. With optimized technology turned off, this election has no effect on the replication topology. Without the optimized topology, all data nodes replicate changes to all other nodes in the cluster. ## Group leaders in the optimized topology - With the optimized topology enabled, only the subscriber-only group's group leader receives changes from other data group's write leaders in the cluster and it takes on the responsibility of replicating those changes to the other nodes in the subscriber-only group. +With the optimized topology enabled, only the subscriber-only group's group leader receives changes from other data groups' write leaders in the cluster. The group leader takes on the responsibility of replicating those changes to the other nodes in the subscriber-only group. The other voting nodes choose the group leader from a subscriber-only group's nodes. -Once selected, the whole cluster becomes aware of the change and any data group's write leaders then replicate data only to this newly selected group leader node. +Once the group leader is selected, the whole cluster becomes aware of the change, and any data group's write leaders then replicate data only to this newly selected group leader node. Other data nodes in the data groups don't replicate data to the subscriber-only group's nodes. This approach avoids the explosion of active connections that can happen when there are large numbers of SO nodes and reduces the amount of replication traffic. -The Subscriber-Only node and group form the building block for PGD tree topologies. +The subscriber-only node and group form the building block for PGD tree topologies. ## Enabling the optimized model By default, PGD 5.6 forces the full mesh topology. This means the optimization described here is off. -To enable the optimized topology, you must have your data-nodes in subgroups, with proxy routing enabled on the sub groups. +To enable the optimized topology, you must have your data nodes in subgroups, with proxy routing enabled on the subgroups. You can then set the GUC [`bdr.force_full_mesh`](/pgd/5.6/reference/pgd-settings#bdrforce_full_mesh) to `off` to allow the optimization to be activated. -Note: This GUC needs to be set in the postgresql.conf file on each data node and each node restarted for the change to take effect. -If any requirements of the optimized topology aren't met, the nodes in a subscriber-only group automatically revert to the full mesh topology. When this happens, you'll find in the logs of the nodes in the cluster messages that explain why the optimization was not possible, such as: +!!! Note + This GUC needs to be set in the `postgresql.conf` file on each data node and each node restarted for the change to take effect. + +If any requirements of the optimized topology aren't met, the nodes in a subscriber-only group revert to the full mesh topology. When this happens, you'll find in the logs of the nodes in the cluster messages why the optimization wasn't possible, such as: When a data node is part of the top-level node group: @@ -67,7 +69,7 @@ When a data node is part of the top-level node group: node: is part of top-level nodegroup: : changing to full mesh". ``` -and when a data group does not have proxy routing enabled: +When a data group doesn't have proxy routing enabled: ```plaintext node: is in nodegroup: that does not have proxy routing: changing to full mesh. diff --git a/product_docs/docs/postgres_distributed_for_kubernetes/1/tde.mdx b/product_docs/docs/postgres_distributed_for_kubernetes/1/tde.mdx index 419f2fb90d8..9761e45ad00 100644 --- a/product_docs/docs/postgres_distributed_for_kubernetes/1/tde.mdx +++ b/product_docs/docs/postgres_distributed_for_kubernetes/1/tde.mdx @@ -1,45 +1,45 @@ --- -title: 'Transparent Data Encryption (TDE)' +title: 'Transparent data encryption (TDE)' originalFilePath: 'src/tde.md' --- !!! Important TDE is available *only* for operands that support it: - EPAS versions 15 and newer, Postgres Extended versions 15 and newer. + EDB Postgres Advanced Server versions 15 and newer and EDB Postgres Extended versions 15 and newer. -Transparent Data Encryption, or TDE, is a technology used by several database -vendors to **encrypt data at rest**, i.e. database files on disk. -TDE does not however encrypt data in use. +Transparent data encryption, or TDE, is a technology used by several database +vendors to encrypt data at rest, that is, database files on disk. +However, TDE doesn't encrypt data in use. -TDE is included in EDB Postgres Advanced Server (EPAS) or EDB Postgres -Extended, starting with version 15, and it is supported by EDB Postgres +TDE is included in EDB Postgres Advanced Server or EDB Postgres +Extended, starting with version 15, and is supported by EDB Postgres Distributed for Kubernetes. !!! Important - Before you proceed, please take some time to familiarize with the - [TDE feature in the EPAS documentation](https://www.enterprisedb.com/docs/tde/latest/). + Before you proceed, take some time to familiarize with the + [TDE feature in the EDB Postgres Advanced Server documentation](/tde/latest/). -With TDE activated, both WAL files and files for tables will be encrypted. -Data encryption/decryption is entirely transparent to the user, as it is +With TDE activated, both WAL files and files for tables are encrypted. +Data encryption/decryption is entirely transparent to the user, as it's managed by the database without requiring any application changes or updated client drivers. The support for TDE on EDB Postgres Distributed for Kubernetes relies on the -implementation from EDB Postgres for Kubernetes (PG4K). Please refer to -[the PG4K documentation](https://www.enterprisedb.com/docs/postgres_for_kubernetes/latest/tde/) +implementation from EDB Postgres for Kubernetes (PG4K). See +[the PG4K documentation](/postgres_for_kubernetes/latest/tde/) for the full context. -We show now how to use TDE with a passphrase stored in a Kubernetes Secret, -which will be used to encrypt the EPAS binary key. +You can use TDE with a passphrase stored in a Kubernetes secret, +which is used to encrypt the EDB Postgres Advanced Server binary key. -!!! Seealso "EPAS documentation" - Please refer to [the EPAS documentation](https://www.enterprisedb.com/docs/tde/latest/secure_key/) - for details on the EPAS encryption key. +!!! Seealso "EDB Postgres Advanced Server documentation" + See [the EDB Posgres Advanced Server documentation](/tde/latest/secure_key/) + for details on the this encryption key. TDE on EDB Postgres Distributed for Kubernetes relies on the PG4K implementation. -To activate TDE on a cluster, we use the `epas` section of the manifest, -which is within the `cnp` section used for PG4K-level directives such as +Activating TDE on a cluster uses the `epas` section of the manifest, +which is in the `cnp` section used for PG4K-level directives such as storage. Use the `tde` stanza to enable TDE, and set the name of the Kubernetes secret holding the TDE encryption key. @@ -75,27 +75,27 @@ spec: size: 1Gi ``` -Again, please refer to [the PG4K documentation](https://www.enterprisedb.com/docs/postgres_for_kubernetes/latest/tde/) +Again, see [the PG4K documentation](/postgres_for_kubernetes/latest/tde/) for additional depth, including how to create the encryption secret and additional ways of using TDE. -As shown in the [TDE feature documentation](https://www.enterprisedb.com/docs/tde/latest/), -the information will be encrypted at rest. +As shown in the [TDE feature documentation](/tde/latest/), +the information is encrypted at rest. -For example, open a `psql` terminal into one of your data nodes. +For example, open a psql terminal into one of your data nodes. ```sh kubectl exec -ti -- psql app ``` -and create a new table including a text column. +Create a new table including a text column: ```sql create table foo(bar int, baz varchar); insert into foo(bar, baz) values (1, 'hello'), (2, 'goodbye'); ``` -And then verify the location where the newly defined table is stored on disk: +Verify the location where the newly defined table is stored on disk: ```sql select pg_relation_filepath('foo'); @@ -110,7 +110,7 @@ You can open a terminal on the same data node: kubectl exec -ti -- bash ``` -and verify the file has been encrypted. +There, you can verify the file was encrypted: ```sh cd $PGDATA/base/16385 diff --git a/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx b/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx index 3becbdeae40..5777b1bd546 100644 --- a/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx +++ b/product_docs/docs/postgres_for_kubernetes/1/installation_upgrade.mdx @@ -17,37 +17,37 @@ originalFilePath: 'src/installation_upgrade.md' ### Obtaining an EDB subscription token !!! Important - You must obtain an EDB subscription token to install EDB Postgres for Kubernetes. Without a token, you will not be able to access the EDB private software repositories. + You must obtain an EDB subscription token to install EDB Postgres for Kubernetes. You can only access the EDB private software repositories if you have a token. Installing EDB Postgres for Kubernetes requires an EDB Repos 2.0 token to gain access to the EDB private software repositories. -You can obtain the token by visiting your [EDB Account Profile](https://www.enterprisedb.com/accounts/profile). You will have to sign in if you are not already logged in. +You can obtain the token by visiting your [EDB Account Profile](https://www.enterprisedb.com/accounts/profile). You must sign in if you're not already logged in. -Your account profile page displays the token to use next to **Repos 2.0 Token** label. By default, the token is obscured, click the "Show" button (an eye icon) to reveal it. +Your account profile page displays the token to use next to the **Repos 2.0 Token** label. By default, the token is obscured. Select **Show** (the eye icon) to reveal it. Your token entitles you to access one of two repositories: standard or enterprise. -* `standard` - Includes the operator and the EDB Postgres Extended operand images. -* `enterprise` - Includes the operator and the EDB Postgres Advanced and EDB Postgres Extended operand images. +* `standard` — Includes the operator and the EDB Postgres Extended operand images. +* `enterprise` — Includes the operator and the EDB Postgres Advanced and EDB Postgres Extended operand images. -Set the relevant value, determined by your subscription, as an environment variable `EDB_SUBSCRIPTION_PLAN`. +Set the relevant value, determined by your subscription, as an environment variable `EDB_SUBSCRIPTION_PLAN`: ```shell EDB_SUBSCRIPTION_PLAN=enterprise ``` -then set the Repos 2.0 token to an environment variable `EDB_SUBSCRIPTION_TOKEN`. +Then set the Repos 2.0 token to an environment variable `EDB_SUBSCRIPTION_TOKEN`: ```shell EDB_SUBSCRIPTION_TOKEN= ``` !!! Warning - The token is sensitive information. Please ensure that you don't expose it to unauthorized users. + The token is sensitive information. Ensure that you don't expose it to unauthorized users. You can now proceed with the installation. -### Using the Helm Chart +### Using the Helm chart The operator can be installed using the provided [Helm chart](https://github.com/EnterpriseDB/edb-postgres-for-kubernetes-charts). @@ -58,16 +58,15 @@ through a YAML manifest applied via `kubectl`. #### Install the EDB pull secret -Before installing EDB Postgres for Kubernetes, you need to create a pull secret for EDB software in the `postgresql-operator-system` namespace. +Before installing EDB Postgres for Kubernetes, you need to create a pull secret for EDB software in the `postgresql-operator-system` namespace. The pull secret needs to be saved in the namespace where the operator will reside. - -The pull secret needs to be saved in the namespace where the operator will reside. Create the `postgresql-operator-system` namespace using this command: +Create the `postgresql-operator-system` namespace: ```shell kubectl create namespace postgresql-operator-system ``` -To create the pull secret itself, run the following command: +Create the pull secret: ```shell kubectl create secret -n postgresql-operator-system docker-registry edb-pull-secret \ @@ -78,13 +77,13 @@ kubectl create secret -n postgresql-operator-system docker-registry edb-pull-sec #### Install the operator -Now that the pull-secret has been added to the namespace, the operator can be installed like any other resource in Kubernetes, +Now that the pull secret has been added to the namespace, the operator can be installed like any other resource in Kubernetes, through a YAML manifest applied via `kubectl`. -There are two different manifests available depending on your subscription plan: +Two different manifests are available, depending on your subscription plan: -- Standard: The [latest standard operator manifest](https://get.enterprisedb.io/pg4k/pg4k-standard-1.24.1.yaml). -- Enterprise: The [latest enterprise operator manifest](https://get.enterprisedb.io/pg4k/pg4k-enterprise-1.24.1.yaml). +- Standard — The [latest standard operator manifest](https://get.enterprisedb.io/pg4k/pg4k-standard-1.24.1.yaml). +- Enterprise — The [latest enterprise operator manifest](https://get.enterprisedb.io/pg4k/pg4k-enterprise-1.24.1.yaml). You can install the manifest for the latest version of the operator by running: You can install the [latest operator manifest](https://get.enterprisedb.io/cnp/postgresql-operator-1.24.1.yaml) @@ -115,7 +114,7 @@ kubectl cnp install generate \ > cnp_for_specific_namespace.yaml ``` -Please refer to ["`cnp` plugin"](./kubectl-plugin.md#generation-of-installation-manifests) documentation +See the ["`cnp` plugin"](./kubectl-plugin.md#generation-of-installation-manifests) documentation for a more comprehensive example. !!! Warning diff --git a/product_docs/docs/tde/15/about/index.mdx b/product_docs/docs/tde/15/about/index.mdx index 6bf65301b0d..041ff148827 100644 --- a/product_docs/docs/tde/15/about/index.mdx +++ b/product_docs/docs/tde/15/about/index.mdx @@ -1,9 +1,9 @@ --- title: About TDE -description: Learn about TDE, how it works, what it encrypts and why to use it. +description: Learn about TDE, how it works, what it encrypts, and why to use it. indexCards: simple --- -Transparent data encryption (TDE) is an optional feature supported by EDB Postgres Advanced Server and EDB Postgres Extended Server from version 15. +Transparent data encryption (TDE) is an optional feature supported by EDB Postgres Advanced Server and EDB Postgres Extended Server in version 15 and later. It encrypts user data stored in the database system. \ No newline at end of file diff --git a/product_docs/docs/tde/15/about/what.mdx b/product_docs/docs/tde/15/about/what.mdx index e478cf5821b..dcf012a9a29 100644 --- a/product_docs/docs/tde/15/about/what.mdx +++ b/product_docs/docs/tde/15/about/what.mdx @@ -5,9 +5,9 @@ description: Which data is encrypted when databases are initialized with TDE? TDE encrypts: -- The files underlying tables, sequences, indexes, including TOAST tables and system catalogs, and including all forks. These files are known as *data files*. +- The files underlying tables, sequences, and indexes, including TOAST tables and system catalogs and all forks. These files are known as *data files*. -- The write-ahead log (WAL). +- The write-ahead log (WAL). - Various temporary files that are used during query processing and database system operation. @@ -17,14 +17,14 @@ TDE encrypts: - A physical replica is necessarily encrypted (or not encrypted) in the same way and using the same keys as its primary server. - - If a server uses TDE, a base backup is automatically encrypted. + - If a server uses TDE, a base backup is encrypted. The following aren't encrypted or otherwise disguised by TDE: - Metadata internal to operating the database system that doesn't contain user data, such as the transaction status (for example, pg_subtrans and pg_xact). -- The file names and file system structure in the data directory. That means that the overall size of the database system, the number of databases, the number of tables, their relative sizes, as well as file system metadata such as last access time are all visible without decryption. +- The file names and file system structure in the data directory. That means that the overall size of the database system, the number of databases, the number of tables, their relative sizes, as well as file system metadata, such as last access time, are all visible without decryption. - Data in foreign tables. diff --git a/product_docs/docs/tde/15/about/why.mdx b/product_docs/docs/tde/15/about/why.mdx index 67395d2c6da..24d2e36cd4f 100644 --- a/product_docs/docs/tde/15/about/why.mdx +++ b/product_docs/docs/tde/15/about/why.mdx @@ -5,18 +5,18 @@ description: Learn about some of the use cases for TDE encryption. TDE encryption ensures that user data remains protected from unauthorized access. -When configured with a [data encryption key securing mechanism](../secure_key/), data stored on the database server and in backup is only accessible by users and processes with decryption keys. +When configured with a [data encryption key securing mechanism](../secure_key/), data stored on the database server and in backup is accessible only by users and processes with decryption keys. -Some use cases include: +Some use cases include: -- **Protection of sensitive personal data:** Industries like finance, e-commerce, healthcare, and government organizations often deal with personally identifiable information that must be protected to comply with data privacy regulations such as GDPR, HIPPA, PCI DSS. +- **Protection of sensitive personal data.** Industries like finance, e-commerce, healthcare, and government organizations often deal with personally identifiable information that must be protected to comply with data privacy regulations such as GDPR, HIPAA, and PCI DSS. -- **Compliance with government standards:** Government institutions must comply with information processing standards like FIPS to ensure computer security and interoperability. +- **Compliance with government standards.** Government institutions must comply with information processing standards like FIPS to ensure computer security and interoperability. -- **Protection of transactional data:** Financial institutions deal with transaction, account, and payment data that must be protected to prevent fraud and financial losses. +- **Protecting transactional data.** Financial institutions deal with transaction, account, and payment data that must be protected to prevent fraud and financial losses. -- **Protection of intellectual property:** Organizations safeguard proprietary information, designs, and plans to keep their competitive advantage, support brand value, and foster innovation. +- **Protecting intellectual property.** Organizations safeguard proprietary information, designs, and plans to keep their competitive advantage, support brand value, and foster innovation. -- **Protection of data in cloud-based deployments and public web applications:** Encrypting a database's data provides an additional layer of security when infrastructure is shared, or when vulnerabilities could potentially infiltrate in an application's API. +- **Protecting data in cloud-based deployments and public web applications.** Encrypting a database's data provides an added layer of security when infrastructure is shared or when vulnerabilities could potentially infiltrate in an application's API. When your data is encrypted, it becomes unintelligible if it's stolen or misplaced. \ No newline at end of file diff --git a/product_docs/docs/tde/15/affected_commands.mdx b/product_docs/docs/tde/15/affected_commands.mdx index 197c2ccf2ed..0da108edb2f 100644 --- a/product_docs/docs/tde/15/affected_commands.mdx +++ b/product_docs/docs/tde/15/affected_commands.mdx @@ -1,6 +1,6 @@ --- title: "Commands affected by TDE" -description: Some commands work differently when TDE is enabled. Learn about differences. +description: How TDE changes the behavior of some commands when enabled. --- When TDE is enabled, the following commands have TDE-specific options or read TDE settings in environment variables or configuration files: diff --git a/product_docs/docs/tde/15/enabling/enabling_tde.mdx b/product_docs/docs/tde/15/enabling/enabling_tde.mdx index 0f698e507cc..af63e7559ab 100644 --- a/product_docs/docs/tde/15/enabling/enabling_tde.mdx +++ b/product_docs/docs/tde/15/enabling/enabling_tde.mdx @@ -12,21 +12,20 @@ Create a new EDB Postgres Advanced Server cluster with TDE enabled. ## Worked example -This example uses EDB Postgres Advanced Server 15 running on a Linux platform. It uses openssl to define the passphrase to wrap and unwrap the generated data encryption key. +This example uses EDB Postgres Advanced Server 15 running on a Linux platform. It uses OpenSSL to define the passphrase to wrap and unwrap the generated data encryption key. 1. Set the data encryption key (wrap) and decryption (unwrap) environment variables: ```shell - export PGDATAKEYWRAPCMD='openssl enc -e -aes-128-cbc -pass pass:ok -out %p' - export PGDATAKEYUNWRAPCMD='openssl enc -d -aes-128-cbc -pass pass:ok -in %p' + export PGDATAKEYWRAPCMD='openssl enc -e -aes-128-cbc -pass pass: -out %p' + export PGDATAKEYUNWRAPCMD='openssl enc -d -aes-128-cbc -pass pass: -in %p' ``` + !!!note - - If you are on Windows you don't need the single quotes around the variable value. - - - Ensure you replace `ok` with the passphrase you want to use to wrap the data encryption key. + - If you're on Windows, you don't need the single quotes around the variable value. !!! -1. Initialize the cluster using `initdb` with encryption enabled. This command sets the `data_encryption_key_unwrap_command` parameter in the postgresql.conf file. +1. Initialize the cluster using `initdb` with encryption enabled. This command sets the `data_encryption_key_unwrap_command` parameter in the `postgresql.conf` file. ```shell /usr/edb/as15/bin/initdb --data-encryption -D /var/lib/edb/as15/data @@ -38,12 +37,12 @@ This example uses EDB Postgres Advanced Server 15 running on a Linux platform. I /usr/edb/as15/bin/pg_ctl -D /var/lib/edb/as15/data start ``` -1. Run grep on postgresql.conf to verify the setting of `data_encryption_key_unwrap_command`: +1. Run grep on `postgresql.conf` to verify the setting of `data_encryption_key_unwrap_command`: ```shell grep data_encryption_key_unwrap_command /var/lib/edb/as15/data/postgresql.conf __OUTPUT__ - data_encryption_key_unwrap_command = 'openssl enc -d -aes-128-cbc -pass pass:ok -in %p' + data_encryption_key_unwrap_command = 'openssl enc -d -aes-128-cbc -pass pass: -in %p' ``` -1. [Verify that data encryption is enabled](verifying_tde). \ No newline at end of file +1. [Verify that data encryption is enabled](verifying_tde). diff --git a/product_docs/docs/tde/15/enabling/enabling_tde_epas.mdx b/product_docs/docs/tde/15/enabling/enabling_tde_epas.mdx index 769cd2e69a2..d05c9b123b7 100644 --- a/product_docs/docs/tde/15/enabling/enabling_tde_epas.mdx +++ b/product_docs/docs/tde/15/enabling/enabling_tde_epas.mdx @@ -1,36 +1,36 @@ --- -title: "Enabling TDE on an existing EDB Postgres Advanced Server" -description: Migrate your existing EDB Postgres Advanced Server to a new TDE-enabled database server. +title: "Enabling TDE on an existing EDB Postgres Advanced Server cluster" +description: Migrate your existing EDB Postgres Advanced Server cluster to a new TDE-enabled database server. deepToC: true redirects: - /tde/latest/enabling_tde_epas/ #generated for TDE/refresh --- -Create a new EDB Postgres Advanced Server cluster with TDE enabled -and use `pg_upgrade` to transfer data from the existing source cluster to the new encrypted cluster. +Create an EDB Postgres Advanced Server cluster with TDE enabled +and use pg_upgrade to transfer data from the existing source cluster to the new encrypted cluster. - [Prepare your upgrade](#preparing-your-upgrade) by performing a backup of the existing instance. -- [Create a new database server](#creating-an-encrypted-server) - - Create an empty directory for the new server and ensure `enterprisedb` owns it. +- [Create a new database server](#creating-an-encrypted-server): + - Create an empty directory for the new server and ensure enterprisedb owns it. - Set the environment variables to export the `wrap` and `unwrap` commands for encryption. - Initialize a server with encryption enabled. - - Change the default port, so the new server is available at another port. + - Change the default port so the new server is available at another port. - Start the database server. - - Connect to the database server and ensure it is functioning. -- [Upgrade to the encrypted server](#upgrading-to-the-encrypted-server) + - Connect to the database server and ensure it's functioning. +- [Upgrade to the encrypted server](#upgrading-to-the-encrypted-server): - Stop both the source and the new server. - - Use `pg_upgrade` with `--copy-by-block` option to copy data from the source server to the new server. Specify the source and target bin and data directories. - - Start the new encrypted databaser server. - - Connect to the encrypted database server and ensure the data was transfered. -- [Clean up and delete the source server](#cleaning-up-after-upgrade) + - Use pg_upgrade with the `--copy-by-block` option to copy data from the source server to the new server. Specify the source and target bin and data directories. + - Start the new encrypted database server. + - Connect to the encrypted database server and ensure the data was transferred. +- [Clean up and delete the source server](#cleaning-up-after-upgrade): - Clean up the database and its statistics. - - Remove the source EDB Postgres Advanced Server cluster with the script provided by `pg_upgrade`. + - Remove the source EDB Postgres Advanced Server cluster with the script provided by pg_upgrade. ## Worked example -This example enables Transparent Data Encryption on an EDB Postgres Advanced Server version 16 running on an Ubuntu 22.04 machine. +This example enables TDE on EDB Postgres Advanced Server version 16 running on an Ubuntu 22.04 machine. -A similar workflow applies to other versions of EDB Postgres Advanced Server and EDB Postgres Extended Server. Note that the location of the BIN and CONFIG directories differs depending on your operating system and the Postgres version. +A similar workflow applies to other versions of EDB Postgres Advanced Server and EDB Postgres Extended Server. The location of the bin and config directories differs depending on your operating system and the Postgres version. ### Preparing your upgrade @@ -44,7 +44,7 @@ Use [pg_dumpall](https://www.postgresql.org/docs/current/app-pg-dumpall.html), [ mkdir /var/lib/edb-as/16/TDE ``` -1. Ensure the `enterprisedb` user owns the directory: +1. Ensure the enterprisedb user owns the directory: ``` sudo chown enterprisedb /var/lib/edb-as/16/TDE @@ -69,7 +69,7 @@ Use [pg_dumpall](https://www.postgresql.org/docs/current/app-pg-dumpall.html), [ /usr/lib/edb-as/16/bin/initdb --data-encryption -D /var/lib/edb-as/16/TDE ``` - This command initializes a CONFIG directory with all configuration files for the encrypted server. + This command initializes a config directory with all configuration files for the encrypted server. 1. Modify the port number in the configuration file of the encrypted instance. Uncomment the line with `#port` and change the port number. For example: @@ -148,7 +148,7 @@ Use [pg_dumpall](https://www.postgresql.org/docs/current/app-pg-dumpall.html), [ ### Cleaning up after upgrade -After you verify that `pg_upgrade` encrypted the data successfully, perform a cleanup. +After you verify that pg_upgrade encrypted the data successfully, perform a cleanup. 1. Clean up the database and its statistics: @@ -156,7 +156,7 @@ After you verify that `pg_upgrade` encrypted the data successfully, perform a cl /usr/lib/edb-as/16/bin/vacuumdb --all --analyze-in-stages ``` -1. Remove all data files of the unencrypted server with the script generated by `pg_upgrade`: +1. Remove all data files of the unencrypted server with the script generated by pg_upgrade: ``` ./delete_old_cluster.sh diff --git a/product_docs/docs/tde/15/enabling/index.mdx b/product_docs/docs/tde/15/enabling/index.mdx index 19f76c0cab8..7724197b18a 100644 --- a/product_docs/docs/tde/15/enabling/index.mdx +++ b/product_docs/docs/tde/15/enabling/index.mdx @@ -9,4 +9,4 @@ navigation: Create a TDE-enabled database server using `initdb`. -Or migrate an existing database instance by creating a TDE-enabled database server with `initdb` and then migrating data with `pg_upgrade`. \ No newline at end of file +Or migrate an existing database instance by creating a TDE-enabled database server with `initdb` and then migrating data with pg_upgrade. \ No newline at end of file diff --git a/product_docs/docs/tde/15/enabling/postgres_to_extended.mdx b/product_docs/docs/tde/15/enabling/postgres_to_extended.mdx index eee6d07c9ab..4e9f507e6e4 100644 --- a/product_docs/docs/tde/15/enabling/postgres_to_extended.mdx +++ b/product_docs/docs/tde/15/enabling/postgres_to_extended.mdx @@ -10,25 +10,25 @@ redirects: Create a new EDB Postgres Extended Server cluster with TDE enabled and use pg_upgrade to transfer data from the existing PostgreSQL cluster to the new encrypted cluster. - [Prepare your upgrade](#preparing-your-upgrade) by performing a backup of the existing instance. -- [Create a new database server](#creating-an-encrypted-server). +- [Create a new database server](#creating-an-encrypted-server): - Create an empty directory for the new server and ensure the postgres user owns it. - Set the environment variables to export the `wrap` and `unwrap` commands for encryption. - Initialize a server with encryption enabled. - Change the default port so the new server is available at another port. - Start the database server. - Connect to the database server and ensure it's functioning. -- [Upgrade to the encrypted server](#upgrading-to-the-encrypted-server). +- [Upgrade to the encrypted server](#upgrading-to-the-encrypted-server): - Stop both the source and the new server. - Use pg_upgrade with the `--copy-by-block` option to copy data from the source server to the new server. Specify the source and target bin and data directories. - Start the new encrypted database server. - Connect to the encrypted database server and ensure the data was transferred. -- [Clean up and delete the source server](#cleaning-up-after-upgrade). +- [Clean up and delete the source server](#cleaning-up-after-upgrade): - Clean up the database and its statistics. - Remove the source PostgreSQL cluster with the script provided by pg_upgrade. ## Worked example -This example upgrades a PostgreSQL 16 instance to EDB Postgres Extended Server 16 while enabling Transparent Data Encryption on an Ubuntu 22.04 machine. The location of the bin and config directories differs depending on your operating system and Postgres versions. +This example upgrades a PostgreSQL 16 instance to EDB Postgres Extended Server 16 while enabling TDE on an Ubuntu 22.04 machine. The location of the bin and config directories differs depending on your operating system and Postgres versions. ### Preparing your upgrade diff --git a/product_docs/docs/tde/15/initdb_tde.mdx b/product_docs/docs/tde/15/initdb_tde.mdx index 19a306435c7..0a96aa3c614 100644 --- a/product_docs/docs/tde/15/initdb_tde.mdx +++ b/product_docs/docs/tde/15/initdb_tde.mdx @@ -9,16 +9,16 @@ Initializing a TDE-enabled server requires two mandatory settings: one enables T To create a TDE-enabled database server, you must use the [`--data-encryption` option](initdb_tde_options/#option---data-encryption-or--y), which creates a data encryption key to encrypt your server. -If you want to copy a key from an existing cluster when preparing a new cluster as a target for pg_upgrade, additionally use the [`--copy-key-from=` option](initdb_tde_options/#option---copy-key-fromfile). +If you want to copy a key from an existing cluster when preparing a new cluster as a target for pg_upgrade, also use the [`--copy-key-from=` option](initdb_tde_options/#option---copy-key-fromfile). ## To protect the data encryption key -When creating a TDE-enabled database, TDE generates a data encryption key that is transparent to the user. +When creating a TDE-enabled database, TDE generates a data encryption key that's transparent to the user. -An additional protection mechanism in the form or a wrapping and an unwrapping command is required to wrap this key, which you must make available to the database server. +An added protection mechanism in the form or a wrapping and an unwrapping command is required to wrap this key, which you must make available to the database server. -See [Providing the wrapping and unwrapping commands to TDE](secure_key) for an overview of the available protection mechanism, and examples of how to provide this configuration to `initdb`. +See [Providing the wrapping and unwrapping commands to TDE](secure_key) for an overview of the available protection mechanism and examples of how to provide this configuration to `initdb`. ## Options reference -See [initdb TDE options](initdb_tde_options) for an overview of all mandatory and elective options and supported values. \ No newline at end of file +See [initdb TDE options](initdb_tde_options) for an overview of all mandatory and elective options and supported values. \ No newline at end of file diff --git a/product_docs/docs/tde/15/initdb_tde_options.mdx b/product_docs/docs/tde/15/initdb_tde_options.mdx index 785fdae0914..9b0387b0f1f 100644 --- a/product_docs/docs/tde/15/initdb_tde_options.mdx +++ b/product_docs/docs/tde/15/initdb_tde_options.mdx @@ -21,9 +21,9 @@ Provides the wrapping/encryption command to protect the data encryption key. `` is customizable, but it must contain the placeholder `%p`. See [Wrapping commands](secure_key/#configuring-a-wrapping-and-unwrapping-command) for examples and information. See [Securing the data encryption key](secure_key) for an overview of available wrapping mechanisms. -If not specified, TDE falls back on the environment variable `PGDATAKEYWRAPCMD`. +If you don't use this option, TDE falls back on the environment variable `PGDATAKEYWRAPCMD`. -Use `-` if you don't want to apply a wrapping mechanism. +If you don't want to apply a wrapping mechanism, use `-`. ## Option: `--key-unwrap-command=` @@ -33,16 +33,16 @@ Provides the unwrapping/decryption command to access the data encryption key. `` is customizable, but it must contain the placeholder `%p`. See [Configuring wrapping commands](secure_key/#configuring-a-wrapping-and-unwrapping-command) for examples and information. -If not specified, TDE falls back on the environment variable `PGDATAKEYUNWRAPCMD`. +If you don't use this option, TDE falls back on the environment variable `PGDATAKEYUNWRAPCMD`. -Use `-` if you didn't apply a wrapping mechanism. +If you didn't apply a wrapping mechanism, use `-` . ## Option: `--no-key-wrap` Disables the key wrapping. The data encryption key is instead stored in plaintext in the data directory. (This option is a shortcut for setting both the wrap and the unwrap command to the special value `-`.) !!!Note - Using this option isn't secure. Use it only for testing purposes. + Using this option isn't secure. Only use it for testing purposes. !!! If you select data encryption and don't specify this option, then you must provide a key wrap and unwrap command. Otherwise, `initdb` terminates with an error. @@ -53,7 +53,7 @@ The `--no-key-wrap` option doesn't require specifying any values. ## Option: `--copy-key-from=` -Copies an existing data encryption key from the provided location. For example, when reusing a key from an existing server during an upgrade with pg_upgrade. +Copies an existing data encryption key from the provided location, for example, when reusing a key from an existing server during an upgrade with pg_upgrade. ### Supported values diff --git a/product_docs/docs/tde/15/overview.mdx b/product_docs/docs/tde/15/overview.mdx index b99f543cbf2..b8756512cab 100644 --- a/product_docs/docs/tde/15/overview.mdx +++ b/product_docs/docs/tde/15/overview.mdx @@ -6,19 +6,19 @@ redirects: - /tde/latest/enabling_tde/ --- -If you want to start using Transparent Data Encryption (TDE) on your database, you either want to create a new TDE-enabled database server, or you want to migrate an existing database server to a TDE-enabled environment. It is not possible to enable TDE on existing instances. +If you want to start using Transparent Data Encryption (TDE) on your database, you'll want to either create a TDE-enabled database server or migrate an existing database server to a TDE-enabled environment. It isn't possible to enable TDE on existing instances. -Regardless of whether you are creating a database server from scratch, or creating a new instance to migrate an existing database server, you have to create a TDE-enabled database by initializing a database cluster using [initdb](https://www.postgresql.org/docs/15/app-initdb.html). +Regardless of whether you're creating a database server from scratch or creating an instance to migrate an existing database server, you have to create a TDE-enabled database by initializing a database cluster using [initdb](https://www.postgresql.org/docs/15/app-initdb.html). ## Before you begin - Choose a method to [secure the data encryption key](secure_key) generated by TDE. - You can protect they key with a [passphrase](./secure_key/passphrase/), a wrapping key from a [key store](secure_key/key_store/) or choose [not protect the key](secure_key/disabling_key/) for testing purposes. + You can protect the key with a [passphrase](./secure_key/passphrase/) or a wrapping key from a [key store](secure_key/key_store/). Or, for testing purposes, you can choose to [not protect the key](secure_key/disabling_key/). -- Review the [initdb TDE options](./initdb_tde_options/) to ensure you have all information required for the initialization of a TDE-enabled database cluster. +- Review the [initdb TDE options](./initdb_tde_options/) to ensure you have all information required for initializing a TDE-enabled database cluster. -- Review the [Limitations and TDE-specific options](./limitations/) to understand limitations and changes in the handling of PostgreSQL utilities when you enable TDE. +- Review [Limitations and TDE-specific options](./limitations/) to understand limitations and changes in the handling of PostgreSQL utilities when you enable TDE. - If you plan on migrating data from an existing database server, ensure you perform a backup of the source database server. @@ -38,29 +38,26 @@ See [Tutorials](#tutorials) for detailed initialization examples. ## Migrating data (for existing instances) -If you want to migrate data and objects from an existing database server, use `pg_upgrade` to copy data from an exiting instance: +If you want to migrate data and objects from an existing database server, use pg_upgrade to copy data from an existing instance. 1. Stop both the source and new server. -1. Use `pg_upgrade` with `--copy-by-block` option to copy data from the source server to the new server. Include other [TDE pg_upgrade options](pg_upgrade_arguments) as required. +1. Use pg_upgrade with the `--copy-by-block` option to copy data from the source server to the new server. Include other [TDE pg_upgrade options](pg_upgrade_arguments) as required. 1. Start the new encrypted database server. -1. Connect to the encrypted database server and ensure the data was transfered. +1. Connect to the encrypted database server and ensure the data was transferred. 1. Perform any required cleanup operations. !!!note -See [TDE pg_upgrade use cases](upgrading) for an overview of the supported enablement and migration use cases. +See [TDE pg_upgrade use cases](upgrading) for an overview of the supported use cases for enabling and migrating. !!! See [Tutorials](#tutorials) for detailed migration examples. ## Tutorials -* [Creating a TDE-enabled database server](enabling/enabling_tde/). -* [Enabling TDE on an existing EDB Postgres Advanced Server database cluster](enabling/enabling_tde_epas/). -* [Upgrading a PostgreSQL database server to EDB Postgres Extended Server while enabling TDE](enabling/postgres_to_extended/). - - - +* [Creating a TDE-enabled database server](enabling/enabling_tde/) +* [Enabling TDE on an existing EDB Postgres Advanced Server database cluster](enabling/enabling_tde_epas/) +* [Upgrading a PostgreSQL database server to EDB Postgres Extended Server while enabling TDE](enabling/postgres_to_extended/) diff --git a/product_docs/docs/tde/15/secure_key/disabling_key.mdx b/product_docs/docs/tde/15/secure_key/disabling_key.mdx index 46c960241b1..bdf8edb7e19 100644 --- a/product_docs/docs/tde/15/secure_key/disabling_key.mdx +++ b/product_docs/docs/tde/15/secure_key/disabling_key.mdx @@ -1,9 +1,9 @@ --- title: Disabling the key wrapping -description: Learn how skip using a wrapping key. +description: Learn how to omit using a wrapping key. deepToc: true --- If you don't want key wrapping, for example for testing, then you must set the wrap and unwrap commands to the special value `-`. -This setting specifies to use the key from the file without further processing. This approach differs from not setting a wrap or unwrap command at all, and from setting either/both to an empty string. Having no wrap or unwrap command set when transparent data encryption is used leaves your data encryption key unsecured, and results in a fatal error when running an affected utility program. +This setting specifies to use the key from the file without further processing. This approach differs from not setting a wrap or unwrap command at all and from setting either or both to an empty string. Having no wrap or unwrap command set when TDE is used leaves your data encryption key unsecured and results in a fatal error when running an affected utility program. diff --git a/product_docs/docs/tde/15/secure_key/index.mdx b/product_docs/docs/tde/15/secure_key/index.mdx index 65627758901..45ef27d8b51 100644 --- a/product_docs/docs/tde/15/secure_key/index.mdx +++ b/product_docs/docs/tde/15/secure_key/index.mdx @@ -13,29 +13,29 @@ redirects: ## Data encryption key -The key for transparent data encryption (the data key) is generated by `initdb` and stored in a file `pg_encryption/key.bin` under the data directory. This file actually contains several keys that are used for different purposes at run time. The data key is a single sequence of random bytes in the file. +The key for transparent data encryption (the data key) is generated by `initdb` and stored in a file `pg_encryption/key.bin` under the data directory. This file contains several keys that are used for different purposes at runtime. The data key is a single sequence of random bytes in the file. -Without any further action, this file contains the key in plaintext, which isn't secure. Anyone with access to the encrypted data directory has access to the plaintext key, which defeats the purpose of encryption. +If you don't perform any further action, this file contains the key in plaintext, which isn't secure. Anyone with access to the encrypted data directory has access to the plaintext key, which defeats the purpose of encryption. ## Choosing a mechanism to protect the data encryption key -To secure the data encryption key, you must specify a wrap and a unwrap command that provides TDE with a data encryption protection mechanism. You can set this parameter only at server start. +To secure the data encryption key, you must specify a wrap and an unwrap command that provides TDE with a data encryption protection mechanism. You can set this parameter only at server start. With the wrap and unwrap commands you can: - [Protect the data key with a passphrase](passphrase). A wrapping key is derived from the passphrase and used to encrypt the data key. -- [Protect the data key with a wrapping key stored in a Key Management System](key_store) or key store. This second key is also called the *key-wrapping key* or *master key*. +- [Protect the data key with a wrapping key stored in a key management system](key_store) or key store. This second key is also called the *key-wrapping key* or *master key*. -- You can also choose to [Disable the data encryption key wrapping](disabling_key). Do this only for test environments, as it leaves the TDE key unprotected. +- You can also choose to [disable the data encryption key wrapping](disabling_key). Only do this for test environments, as it leaves the TDE key unprotected. ## Configuring a wrapping and unwrapping command -After you have chosen a method to protect your key, you can create the wrapping/unwrapping commands. The configuration of these commands is left to the user, which allows tailoring the setup to local requirements and integrating with existing key management software or similar. +After you choose a method to protect your key, you can create the wrapping/unwrapping commands. The configuration of these commands is left to the user, which allows you to tailor the setup to local requirements and integrate with existing key management software or similar. + +[Using a passphrase](passphrase) provides an example for wrapping and unwrapping commands using OpenSSL and a passphrase to secure the TDE data key. [Using a key store](key_store) provides an example for wrapping and unwrapping commands using an external key store key to protect the TDE data key. -The [Using a passphrase](passphrase) topic provides an example for wrapping/unwrapping commands using OpenSSL and a passphrase to secure the TDE data key. The [Using a key store](key_store) topic provides an example for wrapping/unwrapping commands using an external key store key to protect the TDE data key. - -When you initialize a server with TDE, the `initdb` command adds the `data_encryption_key_unwrap_command` parameter in the `postgresql.conf` configuration file. The string specified in `data_encryption_key_unwrap_command` is then able to unwrap (decrypt) the data encryption key. +When you initialize a server with TDE, the `initdb` command adds the `data_encryption_key_unwrap_command` parameter in the `postgresql.conf` configuration file. The string specified in `data_encryption_key_unwrap_command` can then unwrap (decrypt) the data encryption key. The commands must contain a placeholder `%p`, which is replaced with the name of the file containing the key to unwrap. The command must print the unwrapped (decrypted) key to its standard output. @@ -43,7 +43,7 @@ The commands must contain a placeholder `%p`, which is replaced with the name of You must make the commands available to the TDE database server so it can wrap and unwrap the data encryption key. You have the following options: -- You can configure the wrapping and unwrapping commands as environment variables before creating the database, so TDE can fall back on those variables when initializing a server. +- You can configure the wrapping and unwrapping commands as environment variables before creating the database, so TDE can fall back on those variables when initializing a server:
Example @@ -58,7 +58,7 @@ You must make the commands available to the TDE database server so it can wrap a

-- You can provide the wrapping and unwrapping commands directly in the command line when initializing a server with the `--key-wrap-command=` and `--key-unwrap-command=` options. +- You can provide the wrapping and unwrapping commands directly in the command line when initializing a server with the `--key-wrap-command=` and `--key-unwrap-command=` options:
Example @@ -69,7 +69,7 @@ You must make the commands available to the TDE database server so it can wrap a

-- You can disable the protection of your data encryption key with `--no-key-wrap`. This leaves your key unprotected and is recommended for testing proposes only. +- You can disable the protection of your data encryption key with `--no-key-wrap`. Doing so leaves your key unprotected and we recommend this practice only for testing purposes.
Example @@ -79,6 +79,3 @@ You must make the commands available to the TDE database server so it can wrap a

- - - diff --git a/product_docs/docs/tde/15/secure_key/key_rotation.mdx b/product_docs/docs/tde/15/secure_key/key_rotation.mdx index f3d2968ae2d..a24799b5d33 100644 --- a/product_docs/docs/tde/15/secure_key/key_rotation.mdx +++ b/product_docs/docs/tde/15/secure_key/key_rotation.mdx @@ -4,29 +4,33 @@ description: Learn how to rotate your data encryption key. deepToc: true --- -To change the master key, manually run the unwrap command specifying the old key. Then feed the result into the wrap command specifying the new key. Equivalently, if the data key is protected by a passphrase, to change the passphrase, run the unwrap command using the old passphrase. Then feed the result into the wrap command using the new passphrase. You can perform these operations while the database server is running. The wrapped data key in the file is used only on startup. It isn't used while the server is running. +To change the master key, manually run the unwrap command, specifying the old key. Then feed the result into the wrap command, specifying the new key. + +If the data key is protected by a passphrase, to change the passphrase, run the unwrap command using the old passphrase. Then feed the result into the wrap command using the new passphrase. + +You can perform these operations while the database server is running. The wrapped data key in the file is used only on startup. It isn't used while the server is running. ## Rotating the passphrase -Building on the example in [Using a passphrase](passphrase), which uses openssl, to change the passphrase, you can: +Building on the example in [Using a passphrase](passphrase), which uses OpenSSL, to change the passphrase, you can use this approach: ```shell cd $PGDATA/pg_encryption/ openssl enc -d -aes-128-cbc -pbkdf2 -in key.bin | openssl enc -e -aes-128-cbc -pbkdf2 -out key.bin.new mv key.bin.new key.bin ``` -With this method, the decryption and the encryption commands ask for the passphrase on the terminal at the same time, which is awkward and confusing. An alternative is: +With this method, the decryption and the encryption commands ask for the passphrase on the terminal at the same time, which is awkward and confusing. An alternative is: ```shell cd $PGDATA/pg_encryption/ openssl enc -d -aes-128-cbc -pbkdf2 -in key.bin -pass pass:ACTUALPASSPHRASE | openssl enc -e -aes-128-cbc -pbkdf2 -out key.bin.new mv key.bin.new key.bin ``` -This technique leaks the old passphrase, which is being replaced anyway. openssl supports a number of other ways to supply the passphrases. +This technique leaks the old passphrase, which is being replaced anyway. OpenSSL supports a number of other ways to supply the passphrases. ## Rotating the key store wrapping key -When using a [key store](key_store), you can connect the unwrap and wrap commands similarly, for example: +When using a [key store](key_store), you can connect the unwrap and wrap commands similarly. For example: ```shell cd $PGDATA/pg_encryption/ diff --git a/product_docs/docs/tde/15/secure_key/key_store.mdx b/product_docs/docs/tde/15/secure_key/key_store.mdx index 7fedbfe96c7..55396044979 100644 --- a/product_docs/docs/tde/15/secure_key/key_store.mdx +++ b/product_docs/docs/tde/15/secure_key/key_store.mdx @@ -32,7 +32,7 @@ PGDATAKEYWRAPCMD='aws kms encrypt --key-id alias/pg-tde-master-1 --plaintext fil PGDATAKEYUNWRAPCMD='aws kms decrypt --key-id alias/pg-tde-master-1 --ciphertext-blob fileb://"%p" --output text --query Plaintext | base64 -d' ``` !!! Note - Shell commands with pipes, as in this example, are problematic because the exit status of the pipe is that of the last command. A failure of the first, more interesting command isn't reported properly. Postgres handles this somewhat by recognizing whether the wrap or unwrap command wrote nothing. However, it's better to make this more robust. For example, use the `pipefail` option available in some shells or the `mispipe` command available on some operating systems. Put more complicated commands into an external shell script or other program instead of defining them inline. + Shell commands with pipes, as in this example, are problematic because the exit status of the pipe is that of the last command. A failure of the first, more interesting command isn't reported properly. Postgres handles this somewhat by recognizing whether the wrap or unwrap command wrote nothing. However, it's better to make this command more robust. For example, use the `pipefail` option available in some shells or the `mispipe` command available on some operating systems. Put more complicated commands into an external shell script or other program instead of defining them inline. ## Azure Key Vault example @@ -49,7 +49,7 @@ PGDATAKEYWRAPCMD='az keyvault key encrypt --name pg-tde-master-1 --vault-name pg PGDATAKEYUNWRAPCMD='az keyvault key decrypt --name pg-tde-master-1 --vault-name pg-tde --algorithm A256GCM --value @"%p" --data-type plaintext --only-show-errors --output json | jq -r .result' ``` !!! Note - Shell commands with pipes, as in this example, are problematic because the exit status of the pipe is that of the last command. A failure of the first, more interesting command isn't reported properly. Postgres handles this somewhat by recognizing whether the wrap or unwrap command wrote nothing. However, it's better to make this more robust. For example, use the `pipefail` option available in some shells or the `mispipe` command available on some operating systems. Put more complicated commands into an external shell script or other program instead of defining them inline. + Shell commands with pipes, as in this example, are problematic because the exit status of the pipe is that of the last command. A failure of the first, more interesting command isn't reported properly. Postgres handles this somewhat by recognizing whether the wrap or unwrap command wrote nothing. However, it's better to make this command more robust. For example, use the `pipefail` option available in some shells or the `mispipe` command available on some operating systems. Put more complicated commands into an external shell script or other program instead of defining them inline. ## Google Cloud KMS example @@ -89,7 +89,7 @@ PGDATAKEYUNWRAPCMD='vault write -field=plaintext transit/decrypt/pg-tde-master-1 ## Thales CipherTrust Manager example -See the [Using](/partner_docs/ThalesCipherTrustManager/05-UsingThalesCipherTrustManager/) section of the [Implementing Thales CipherTrust Manager](/partner_docs/ThalesCipherTrustManager/) documentation for instructions how to wrap the data encryption key with a key from the Thales key store. +See [Using](/partner_docs/ThalesCipherTrustManager/05-UsingThalesCipherTrustManager/) in the [Implementing Thales CipherTrust Manager](/partner_docs/ThalesCipherTrustManager/) documentation for instructions on how to wrap the data encryption key with a key from the Thales key store. ## Fortanix Data Security Manager example diff --git a/product_docs/docs/tde/15/secure_key/passphrase.mdx b/product_docs/docs/tde/15/secure_key/passphrase.mdx index 85054afd213..f09ac41f70f 100644 --- a/product_docs/docs/tde/15/secure_key/passphrase.mdx +++ b/product_docs/docs/tde/15/secure_key/passphrase.mdx @@ -3,7 +3,7 @@ title: Using a passphrase description: Learn how to secure your encryption key with a passphrase. --- -You can protect the data key with a passphrase using the openssl command line utility. The following is an example that sets up this protection: +You can protect the data key with a passphrase using the OpenSSL command line utility. The following is an example that sets up this protection: ```shell initdb -D datadir -y --key-wrap-command='openssl enc -e -aes-128-cbc -pbkdf2 -out "%p"' --key-unwrap-command='openssl enc -d -aes-128-cbc -pbkdf2 -in "%p"' @@ -13,10 +13,9 @@ This example wraps the randomly generated data key (done internally by initdb) b The unwrap command performs the opposite operation. initdb doesn't need the unwrap operation. However, it stores it in the `postgresql.conf` file of the initialized cluster, which uses it when it starts up. - The key wrap command receives the plaintext key on standard input and needs to put the wrapped key at the file system location specified by the `%p` placeholder. The key unwrap command needs to read the wrapped key from the file system location specified by the `%p` placeholder and write the unwrapped key to the standard output. -Utility programs like pg_rewind and pg_upgrade operate directly on the data directory or copies, such as backups. These programs also need to be told about the key unwrap command, depending on the circumstances. They each have command-line options for this purpose. +Utility programs like pg_rewind and pg_upgrade operate directly on the data directory or copies, such as backups. These programs also need to be told about the key unwrap command, depending on the circumstances. They each have command line options for this purpose. To simplify operations, you can also set the key wrap and unwrap commands in environment variables. These are accepted by all affected applications if you don't provide the corresponding command line options. For example: diff --git a/product_docs/docs/tde/15/upgrading.mdx b/product_docs/docs/tde/15/upgrading.mdx index 08fca739777..4dff1169f92 100644 --- a/product_docs/docs/tde/15/upgrading.mdx +++ b/product_docs/docs/tde/15/upgrading.mdx @@ -6,7 +6,8 @@ redirects: - /tde/latest/upgrade_use_cases/ #generated for TDE/refresh --- -You can use the [pg_upgrade](https://www.postgresql.org/docs/current/pgupgrade.html) with additional TDE-arguments to perform a number of upgrading and migrating operations. +You can use [pg_upgrade](https://www.postgresql.org/docs/current/pgupgrade.html) with additional TDE arguments to perform upgrading and migrating operations. + This table provides an overview of supported use cases. | Use case | Source unencrypted server | Target encrypted server | @@ -17,7 +18,7 @@ This table provides an overview of supported use cases. | Maintain the Postgres distribution and rotate encryption keys | Encrypted EDB Postgres Advanced Server 15 | Encrypted EDB Postgres Advanced Server 15 with new encryption keys | !!! Important - Both source and target servers must be in the same Postgres major version. `pg_upgrade` only supports upgrades between minor versions. + Both source and target servers must be in the same Postgres major version. pg_upgrade only supports upgrades between minor versions. ## Tutorials