Only this pageAll pages
1 of 87

En_Tmax OpenSQL 안내서 v1.0.0

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Tmax OpenSQL Installation

OpenSQL 3.0 binary installation

Tmax OpenSQL Administration

OpenProxy

Tmax O2 Extensions

This guide is intended for users of Tmax OpenSQL.

Since Tmax O2 Extensions is an OpenSQL-only extension of TmaxTibero, this is integrated into the OpenSQL documentation as an 'O2 Extensions' topic.

Tmax OpenSQL Overview

Tmax OpenSQL v3.0 is an open source relational database management system(RDBMS) that uses the database cluster that provides high performance and high availability based on PostgreSQL.

Tmax OpenSQL v3.0 Configuration

OpenSQL Components

PostgreSQL

An open-source relational database management system that is scalable and compliant with SQL standards.

Patroni

Performs PostgreSQL database cluster management. It is open source, written in Python, runs as a server process, detects the status of each node, and provides automatic failover, election of a new primary PostgreSQL node, and database configuration management.

An open source Distributed Key-Value Store written in Go language that provides stability, data consistency, and scalability optimized for distributed systems. It stores cluster membership information and configuration information managed by Patroni.

A high-performance connection pooler written in Rust language that provides PostgreSQL connection pooling, load balancing, and VIP Failover features.

An open source PostgreSQL database backup management solution written in Python that offers full, incremental, and differential backups.

Components configuration

The execution order of OpenSQL v3.0 is as follows.

  1. Etcd

  2. Patroni + PostgreSQL

  3. OpenProxy

The configuration and execution for each component are described in the following order.

  • Etcd

  • Patroni

  • OpenProxy

Etcd

Etcd is an open source distributed key-value store. OpenSQL utilizes etcd as a Distributed Configuration Store(DCS) that manages the state of each instance in the cluster and performs leader election, and provides the etcdctl tool for effective control.


Once installed, you can check the version of etcd and etcdctl with the command below.

Patroni

Patroni is a Python 3-based server process and template that provides lifecycle management of PostgreSQL database instances installed on nodes, high availability management through cluster configuration, and cluster management through REST APIs.


The node must have a PostgreSQL server installed and the postgres user configured. Patroni manages the life cycle of the PostgreSQL server directly at runtime by referencing the PostgreSQL server's Data Directory and Binary Directory, which are included in the definition of its PostgreSQL configuration values.

  • The node intended for Patroni installation must be configured with a PostgreSQL server.

OpenProxy

OpenProxy is a Rust-based server process that functions as a proxy for PostgreSQL databases, providing connection pooling, query-based load balancing, database sharding, and failover using virtual IP (VIP).

This document describes how to install OpenProxy from an OpenSQL package created using the OpenSQL packaging tool.


The $OPENSQL_INSTALL_HOME/openproxy directory in the OpenSQL package contains the following three files.

  • Openproxy binary openproxy

Aggregate Functions

Conditional Functions

Reference guide

SQL function

DateTime Functions

Format Functions

Math Functions

Misc Functions

Installation

Release Note

Text Functions

SESSIONTIMEZONE

Syntax

Overview

The sessiontimezone function returns the timezone of the current session as a text value.

Internally, it calls the show_timezone() function to view the time zone of the current session and then converts it to text, and returns it.

Example

DBTIMEZONE

Syntax

Overview

The dbtimezone function returns the server's default time zone in text.

Internally, it looks at the pg_db_role_setting table to determine the settings for the current database.

If it doesn't exist, it will get the default TimeZone value from pg_settings.

In other words, it views the default time zone set on the server and provides it as a string.

Example

SYSTIMESTAMP

Syntax

Overview

The systimestamp function returns the timestamp of the current statement based on the server's time zone.

Internally, it calls GetCurrentTimestamp() to get the timestamp value based on the server's timezone.

Example

SINH

Syntax

Overview

SINH is the hyperbolic sine of num.

Parameter

Arguments
Description

num

It can take a numeric data type or a data type that can be converted to numeric as an argument.

The return type is the same as the numeric data type given as an argument.

Example

SYSDATE

Syntax

Overview

The sysdate function returns the current statement timestamp based on the server time zone.

It runs similarly to Oracle's sysdate, and the returned timestamp is used like Oracle DATE type by removing decimal places.

Example

Example

SYS_GUID

Syntax

SYS_GUID()

Overview

SYS_GUID generates and returns a globally unique identifier consisting of 16 bytes of RAW data.

UUIDs are generated using a pseudorandom method.

Example

COSH

Syntax

Overview

COSH is the hyperbolic cosine of n.

Parameter

Arguments
Description

num

It can take a numeric data type or a data type that can be converted to numeric as an argument.

The return type is the same as the numeric data type given as an argument.

Example

LENGTH

Syntax

Overview

LENGTH returns the length of the given str.

Parameter

Parameter
Description

str

Arbitrary expression that returns a string. It can have CHAR or TEXT type.

In OpenSQL, the Distributed Configuration Store (DCS), such as etcd, must be running before starting Patroni.

Once installed, you can check the version of patroni and patronictl with the command below.

Installation

Requirement

1. Setting OPENSQL_INSTALL_HOME directory

2. Installing Patroni

3. Veryfying Patroni installation

Configuration file required to run (openproxy.toml)

  • Service file required for systemd registration (openproxy.service)

  • You can configure OpenProxy using the supplied configuration files and register it as a service via systemd.

    You can check the version of binary with the command below.

    Installation

    1. Configuring Openproxy

    2. Setting OPENSQL_INSTALL_HOME directory

    3. Installing Openproxy

    4. Verifying Binary execution

    SESSIONTIMEZONE()
    RETURNS text;
    select oracle.sessiontimezone();
    
     sessiontimezone 
    -----------------
     Asia/Seoul
    (1 row)
    DBTIMEZONE()
    RETURNS text;
    select oracle.dbtimezone();
    
     dbtimezone 
    ------------
     Asia/Seoul
    (1 row)
    SYSTIMESTAMP()
    RETURNS timestamptz;
    SELECT oracle.SYSTIMESTAMP();
    
             systimestamp          
    -------------------------------
     2025-03-06 23:41:29.160617+09
    (1 row)
    SINH(num)
    SELECT SINH(0);
     sinh 
    ------
        0
    SYSDATE()
    RETURN TIMESTAMP;
    select oracle.sysdate();
    select oracle.sysdate();
    
           sysdate       
    ---------------------
     2025-03-06 22:39:05
    (1 row)
    SELECT SYS_GUID();
                  sys_guid              
    ------------------------------------
     \xc3a83bc2e6f845c8bdf884af0c0516ac
    (1 row)
    COSH(num)
    SELECT COSH(0);
     cosh 
    ------
        1
    LENGTH(str)
    . ./setenv.sh `pwd`
    OPENSQL_INSTALL_HOME is set to: /home/opensql3.0-rockylinux9.4-pg16.8 
    sudo -E ./install_rpm.sh patroni
    [root@396dd54381db scripts]patroni --version
    patroni 4.0.3
    
    [root@396dd54381db scripts] patronictl version
    patronictl version 4.0.3
    [root@5c9e5c6ae5f2 openproxy]# ls
    openproxy  openproxy.service  openproxy.toml
    . ./setenv.sh `pwd`
    OPENSQL_INSTALL_HOME is set to: /home/opensql3.0-rockylinux9.4-pg16.8
    sudo -E ./install_rpm.sh openproxy
    [root@5c9e5c6ae5f2 openproxy]# openproxy --version
    openproxy 1.0.0
    . ./setenv.sh `pwd`
    OPENSQL_INSTALL_HOME is set to: /home/opensql3.0-rockylinux9.4-pg16.8
    sudo -E ./install_rpm.sh etcd
    [root@396dd54381db etcd-v3.5.6-linux-amd64]etcd --version
    etcd Version: 3.5.6
    Git SHA: cecbe35ce
    Go Version: go1.16.15
    Go OS/Arch: linux/amd64
    
    [root@396dd54381db etcd-v3.5.6-linux-amd64]etcdctl version
    etcdctl version: 3.5.6
    API version: 3.5

    Installation

    1. Setting OPENSQL_INSTALL_HOME directory

    2. Installing etcd

    3. Verifying etcd installation

    Etcd

    OpenProxy

    Barman

    Postgresql

    OpengreSQL is a database package based on PostgreSQL, and this manual will guide you through the basic environment setup for installing OpengreSQL and the PostgreSQL installation process.


    Installation

    1. Setting OPENSQL_INSTALL_HOME directory

    Once you unzip the OpenSQL binaries, you will find the scripts for installing OpenSQL inside the scripts directory, such as setenv.sh , install_rpm.sh .

    . ./setenv.sh `pwd`
    OPENSQL_INSTALL_HOME is set to: /home/opensql3.0-rockylinux9.4-pg16.8

    2. Installing Postgresql

    sudo -E ./install_rpm.sh postgresql

    3. Verifying Postgresql Installation

    Once installed, you can check the the installation path and the version of postgresql with the command below.

    pg_config intalled with a binary from Postgresql is located in the path of /usr/pgsql-{postgresql_Major_version}/bin .

    Architecture Overview

    Introduction to Extensions in PostgreSQL

    PostgreSQL is known for being a highly scalable open source database. A large part of this reputation is due to the Extension Framework, which provides a flexible way to extend PostgreSQL's functionality. Extensions allow PostgreSQL to support a wide variety of data types and functions, and even improve its internal functionality.

    An important feature of extensions is that they are dynamically loaded into the PostgreSQL instance, meaning that PostgreSQL does not need to rebuild the source or replace the executable when adding new functionality through an extension. Adding an extension also doesn't require restarting the instance, except for extensions that require initialization at instance startup. This makes adding new features very easy in PostgreSQL.


    Introduction to O2 Extensions

    O2 stands for OpenSQL for Oracle, which is a set of extensions that provide compatibility with Oracle data types, views, built-in functions, and built-in packages. O2 is based on the open source project Orafce, but it has changed in many ways. Orafce, which was originally managed as a single extension, has been split into multiple extensions.

    O2 Extensions includes the following extensions

    • O2Types: Oracle Data Type Compatibility Extension

    • O2Views: Oracle View Compatibility Extension

    • O2Functions: Oracle Built-in Functions Compatible Extension

    • Package Extensions: A collection of extensions compatible with Oracle's built-in packages.

      • DBMS_ALERT

      • DBMS_OUTPUT

      • DBMS_PIPE

    The O2 project was started based on the open source project Orafce, but it has changed in many ways. Originally managed as a single extension, Orafce was split into several extensions, which greatly increased the flexibility of patching. In addition, the lack of a common convention or framework was a problem due to its gradual development over a long period of time, which was improved during the integration process.


    The built-in functions or packages provided by O2 Extension are internally organized as user-defined functions (UDFs). PostgreSQL supports a variety of programming languages for writing user-defined functions, including SQL and PL/pgSQL, as well as C/C++, Python, Perl, and Rust. The O2 Extension specifically improves performance by turning custom functions written in SQL and PL/pgSQL into C code. When the PostgreSQL Query execution engine executes a UDF written in SQL or PL/pgSQL, it internally creates a cursor to execute subqueries, but functions written in C code are executed directly from the compiled library, ensuring fast performance. In addition, implementing in C code allows for more sophisticated and flexible implementations by utilizing PostgreSQL libraries.

    Since the existing Orafce was managed as a single Extension, if a problem occurred in one element of the entire implementation, the entire Extension had to be updated. On the other hand, O2 is managed by dividing it into several Extensions, so only the Extension that has a problem needs to be replaced.

    For example, packages that use shared memory, such as DBMS_ALERT or DBMS_PIPE, need to be added to shared_preload_libraries and then start the DB instance. However, in the case of O2, these extensions are separated, so that only the necessary extensions can be added to shared_preload_libraries. This has reduced the hassle and increased flexibility during updates.

    These improvements enable the O2 Extension to provide PostgreSQL users with more powerful and flexible Oracle compatibility. The introduction of the O2 Extension provides significant improvements in performance, flexibility, and stability.

    REMAINDER

    Syntax

    REMAINDER(num1, num2);

    Overview

    REMAINDER is a function that returns the remainder of num1 divided by num2.

    MODuses FLOOR, and REMAINDERis similar except that it uses Bankers' Round method.

    Arguments
    Description.

    Connection pool

    The connection pool to create must be specified in the openproxy.toml file.

    Before creating a connection pool, create a PostgreSQL database to use. some_db database is created in this example.

    • Create a section [pools.simple_db] in openproxy.toml.

    MEDIAN

    The MEDIAN aggregate function is a statistical function that calculates and returns the median of the values in a group. It is inspired by Oracle's MEDIAN function and implemented in PostgreSQL.

    It is available for integer, real, and date/time data types. Internally, the MEDIAN function works in two steps.

    • This step collects the values in the group into a type-correct vector (list data structure).

    • NULL values are ignored in the aggregation.

    Tmax OpenSQL Manual

    About the Guide

    Issued date: 2025-05-15 Software version: Tmax OpenSQL v3.0 Guide version: v1.0.0

    The Tmax OpenSQL® (hereafter Tmax OpenSQL) product provides operations and management for the open source PostgreSQL DBMS. This guide is intended for users of Tmax OpenSQL.

    • Database

    Type

    The DATE type is a data type that represents a specific date and time to the nearest second. It has the same range of representation as TIMESTAMP(0).

    • Expresses year, month, day, hour, minute, and second.

    • Years can be expressed from 4,713 BC~ to 294,276 AD.

    • Time is expressed in 24-hour increments.


    LNNVL

    The lnnvl function returns the opposite value for the given boolean value, i.e., false if the argument is true and true if it is false. Also returns true if the argument is NULL.

    Parameter
    Description

    GREATEST

    The GREATEST function returns the largest value among the passed in arguments. If any of the arguments are NULL, the entire result will be NULL.

    The PostgreSQL default function returns NULL only if all arguments are NULL, whereas this function returns NULL if even one is NULL.

    Parameter
    Description

    LEAST

    The LEAST function returns the smallest value among the passed in arguments. If any of the arguments are NULL, the entire result will be NULL.

    The PostgreSQL default function returns NULL if and only if all arguments are NULL, which is NULL if even one is NULL.

    Parameter
    Description

    NANVL

    The NANVL function returns the value of the second argument if the first argument is NaN (Not a Number), otherwise it returns the value of the first argument as it is.

    If the second argument is not varchar, it must be of the same type as the first argument. Used to replace NaN with another value in floating-point or numeric data.

    Parameter
    Description

    LAST_DAY

    The LAST_DAY function returns the last day of the month to which the given date belongs.

    For the DATE type, it simply calculates the last day of the month.

    For the TIMESTAMPTZ type, the date is truncated and the original time information is combined to return a timestamp value.

    Parameter
    Description

    SYS_EXTRACT_UTC

    The SYS_EXTRACT_UTC function converts the given timestamp (with/without time zone) to a timestamp in UTC (without timezone) and returns it.

    For TIMESTAMP (without time zone), the value is interpreted based on the time zone of the session, then converted to a timestamp in UTC and returned.

    In other words, theTIMESTAMP without time zone type is first converted to a TIMESTAMP WITH TIME ZONE, then shifted to the "utc" time zone and returned like a DATE in Oracle.

    Parameter
    Description

    TO_SINGLE_BYTE

    The TO_SINGLE_BYTE function converts the input multibyte string into the corresponding single-byte (ASCII) characters, if possible.

    Multi-byte characters in the input string are replaced with single-byte values (usually values with ASCII code 0x20 or higher) by a predefined mapping table, and unconvertible characters are returned as they are.

    Parameter
    Description

    TO_TIMESTAMP_TZ

    This function converts the input string and format model into a timestamp with time zone (timestamptz) value.

    Utilizes the PostgreSQL built-in to_timestamp function to parse a string according to the specified format and return the result as a timestamptz type.

    Unlike Oracle, it doesn't accept date type variables in order to maintain type consistency.

    Parameter
    Description

    TO_MULTI_BYTE

    The TO_MULTI_BYTE function converts a single-byte (ASCII) character to the corresponding multi-byte character in the database encoding.

    For example, characters in the ASCII range (0x20~ 0x7E) are converted according to a predefined multi- byte mapping table (UTF8, EUC_JP, EUC_CN, etc.).

    If the database encoding corresponds to one of its mapping tables, it replaces each character in the input string with the corresponding multi-byte string, otherwise it returns the characters as they are.

    Parameter
    Description

    MONTHS_BETWEEN

    The MONTHS_BETWEEN function calculates and returns the number of months between two dates (or timestamps).

    The year, month, and day of two dates are compared to calculate the difference in months. If both dates are the last day of the month, it calculates as an integer number of months.

    Otherwise, the difference in days divided by 31 is returned with the decimal point added. In other words, the decimal point value is calculated based on 31 days.

    Parameter
    Description

    DUMP

    DUMP returns TEXT with data type code, length in bytes, and internal representation of expr.

    By default, the return value does not contain character set information.

    To find the character set name of expr ,add 1000 to return_fmt.

    Parameter
    Description

    MOD

    MODis a function that returns the remainder of num1 divided by num2. If num2 is 0, it returns num1.

    This function returns a result that differs from the traditional Modulus function when num1 or num2 is negative.

    The traditional Modulus function is as follows.

    Arguments
    Description

    TANH

    COSH is the hyperbolic cosine of n.

    Arguments
    Description

    DBMS_RANDOM

  • DBMS_SQL

  • UTL_FILE

  • Benefits and improvements of O2 Extensions

    Change custom functions written in SQL, PL/pgSQL to C code

    Reduce blast radius by splitting the extension into multiple extensions

    num1, num2

    num1 and num2 must be numeric types or types that can be converted to numeric types. num1 and num2 are converted to the type with the higher numeric precedence of the two types, and are returned as that type.

    Example

    str

    text type; Target string to convert. Multi-byte characters are converted to single-byte characters.

    Syntax

    Overview

    Parameter

    Example

    num

    It can take a numeric data type or a data type that can be converted to numeric as an argument.

    The return type is the same as the numeric data type given as an argument.

    Syntax

    Overview

    Parameter

    Example

    • Create a section [pools.simple_db.users.0] in openproxy.toml.

    • Create a section in openproxy.toml called [pools.simple_db.shard.0].


    Execute the OpenProxy with the openproxy.toml file that sets up the connection pool to create.


    Check the Connection Pool created by psql -h 127.0.0.1 -p 6432 -d openproxy -U postgres command.

    Connection Pool creation

    simple_db connection pool creation

    Connection Pool to create : simple_db

    Set Connection Pool user information

    List the cluster address and database to connect to

    Full example of a simple_db connection pool creation configuration file

    OpenProxy Execution

    Connection Pool Verification

    • When all the values in the group have been collected, the median value is finally calculated.

    • First, we sort the values in the aggregated vector with a quick sort algorithm.

    • Returns the median value if the number of aggregated values is odd.

    • If the number of aggregated values is even, compute and return the average of the two values in the center. For date and time-related data with time zones, calculate the average value after timezoning the two center values to UTC.

    Calculate the average value in UTC and adopt the timezone of the larger of the two center values.

    Parameter
    Description

    expression

    The value to be aggregated, which supports the

    following data types.

    • Integer types: smallint, int, bigint

    • Real number type: real(float4), double precision

    • Date/Time types: timestamp, timestamptz, time, timetz, date NULL values are ignored when aggregating, and values are stored in internal vectors for each type.

    • If an even number of values are aggregated, the average of the two values in the center is calculated and returned.

    • Internally, the C code uses the qsort function to sort the values.

    • For date and time related data, additional timezone and type conversion processing is performed according to Oracle's processing logic.

    Syntax

    Overview

    Aggregation step

    Final calculation step

    Parameters

    Caution

    Example

    Like the CHARACTER VARYING type, the VARCHAR2 type also has a variable length, where the string length is not constant.

    • A string can be declared up to 10,485,760 bytes (=10 MB). If the length of the converted string exceeds that size, an error is raised.

    • If the size of the string is not specified, it behaves like the Postgresql native type TEXT.

    • The length of the string can be specified in bytes.

    • Always use single quotes (' ') to represent values of type VARCHAR2 in SQL statements.

    The following example illustrates the VARCHAR2 type.

    As shown in the example above, the EMP_NAME column has a string length of 10 bytes. For example, if the string 'Peter' is entered, the string 'Peter' is stored. In other words, the string length of the EMP_NAME column is declared to be 10 bytes, but the actual stored string length is 5 bytes.

    As you can see, the VARCHAR2 type has a length equal to the length of the entered string within the range of the declared string length.


    The NVARCHAR2 type is for storing Unicode strings. It is characterized by having a variable length, where the length of the string is not constant.

    • It is basically similar to the VARCHAR2 type, but the length of the string is in characters. The length of the types stored in the database depends on the multilingual character set. For example, it can be up to three times the size in UTF8 and up to twice the size in UTF16.

    • The maximum length of a string of type NVARCHAR2 is 10,485,760 characters.

    • Always use single quotes (' ') to represent values of type NVARCHAR2 in SQL statements.

    DATE

    VARCHAR2

    NVARCHAR2

    value

    Syntax

    Overview

    Parameters

    boolean type: the boolean value to compare. If NULL, the result is true

    Example

    anynonarray type: the first value to compare. It must be non-NULL.

    expr_array

    variadic anyarray type: an array containing additional arguments. If there is a NULL in the array, the entire result is NULL. Each element of the array must be of the same type as expr1.

    Syntex

    Overview

    Parameters

    expr1

    Example

    anynonarray type: the first value to compare. Must be non-NULL.

    expr_array

    VARIADIC anyarray type: an array containing additional arguments. If there is a NULL in the array, the entire result is NULL.

    The elements of the array must have the same type as expr1.

    Syntax

    Overview

    Parameters

    expr1

    Example

    value

    The numeric value to check (real, double precision, numeric).

    if NaN, returns the replacement value.

    replacement

    The value to return instead when value is NaN (varchar, real , double precision , numeric ). if it is a varchar, it is automatically cast to the type of value.

    Syntax

    Overview

    Parameters

    Example

    date, timestamptz type: the base date to get the last date from. For timestamptz, it is calculated by finding the first day of the month, adding one month and subtracting one day.

    Syntax

    Overview

    Parameters

    value

    Example

    time

    timestamp, timestamptz type: the target timestamp value to convert to UTC. For timestamp, it is internally converted to timestamptz based on the timezone of the session and then converted to UTC.

    Syntax

    Overview

    Parameters

    Example

    text type; String to convert. ASCII

    characters are replaced with multibyte characters.

    Syntax

    Overview

    Parameter

    str

    Example

    date1 / timestamptz1

    date / timestamptz type: the date (or timestamp) value that the comparison is based on.

    date2 / timestamptz2

    date / timestamptz type: date1/timestamptz1 to compare to the target date (or timestamp)

    Syntax

    Overview

    Parameters

    Example

    expr

    Arbitrary expression that can come as a string.

    Returns NULL if expr is NULL.

    return_fmt

    return_fmt specifies the type of the return value and can have one of the following values.

    • 8 returns the result in octal notation.

    start_position

    It indicates the starting position.

    length

    It specifies the length to display.

    • 10 returns the result in decimal.

    • 16 returns the result in hexadecimal.

    • 17 returns each byte output only if it can be interpreted as a printable character in the compiler's character set. Some ASCII characters may be output as ‘?’. Otherwise, they are output in hexadecimal. All NLS parameters are ignored. The DUMP function with return_fmt set to 17 should not depend on any specific output format.

    Syntax

    Overview

    Parameter

    Example

    num1, num2

    num1 and num2 must be numeric types or types that can be converted to numeric types. num1 and num2 are converted to the type with the higher numeric precedence of the two types, and are also returned as that type.

    Syntax

    Overview

    Example

    [root@396dd54381db etcd-v3.5.6-linux-amd64]/usr/pgsql-16/bin/pg_config 
    BINDIR = /usr/pgsql-16/bin
    DOCDIR = /usr/pgsql-16/doc
    HTMLDIR = /usr/pgsql-16/doc/html
    INCLUDEDIR = /usr/pgsql-16/include
    PKGINCLUDEDIR = /usr/pgsql-16/include
    INCLUDEDIR-SERVER = /usr/pgsql-16/include/server
    LIBDIR = /usr/pgsql-16/lib
    PKGLIBDIR = /usr/pgsql-16/lib
    LOCALEDIR = /usr/pgsql-16/share/locale
    MANDIR = /usr/pgsql-16/share/man
    SHAREDIR = /usr/pgsql-16/share
    SYSCONFDIR = /etc/sysconfig/pgsql
    PGXS = /usr/pgsql-16/lib/pgxs/src/makefiles/pgxs.mk
    CONFIGURE =  '--enable-rpath' '--prefix=/usr/pgsql-16' '--includedir=/usr/pgsql-16/include' '--mandir=/usr/pgsql-16/share/man' '--datadir=/usr/pgsql-16/share' '--libdir=/usr/pgsql-16/lib' '--with-lz4' '--with-zstd' '--enable-tap-tests' '--with-icu' '--with-llvm' '--with-perl' '--with-python' '--with-tcl' '--with-tclconfig=/usr/lib64' '--with-openssl' '--with-pam' '--with-gssapi' '--with-includes=/usr/include' '--with-libraries=/usr/lib64' '--enable-nls' '--enable-dtrace' '--with-uuid=e2fs' '--with-libxml' '--with-libxslt' '--with-ldap' '--with-selinux' '--with-systemd' '--with-system-tzdata=/usr/share/zoneinfo' '--sysconfdir=/etc/sysconfig/pgsql' '--docdir=/usr/pgsql-16/doc' '--htmldir=/usr/pgsql-16/doc/html' 'CFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' 'LDFLAGS=-Wl,--as-needed' 'LLVM_CONFIG=/usr/bin/llvm-config-64' 'CLANG=/usr/bin/clang' 'PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig'
    CC = gcc
    CPPFLAGS = -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include
    CFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wshadow=compatible-local -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection
    CFLAGS_SL = -fPIC
    LDFLAGS = -Wl,--as-needed -L/usr/lib64 -L/usr/lib64 -Wl,--as-needed -Wl,-rpath,'/usr/pgsql-16/lib',--enable-new-dtags
    LDFLAGS_EX = 
    LDFLAGS_SL = 
    LIBS = -lpgcommon -lpgport -lselinux -lzstd -llz4 -lxslt -lxml2 -lpam -lssl -lcrypto -lgssapi_krb5 -lz -lreadline -lm 
    VERSION = PostgreSQL 16.8
    SELECT REMAINDER(3,2);
     remainder 
    -----------
            -1
    TO_SINGLE_BYTE
    (
      str  IN text
    )
    RETURNS text;
    SELECT oracle.TO_SINGLE_BYTE('Hello, world!');
    -- example result: 'Hello, world!'
    
     to_single_byte 
    ----------------
     Hello, world!
    (1 row)
    COSH(num)
    SELECT TANH(0);
     tanh 
    ------
        0
    [pools.simple_db.users.0]
    username = "simple_user"
    password = "simple_user"
    pool_size = 5
    statement_timeout = 30000
    [pools.simple_db.shards.0]
    servers = [
      [ "opensql1", 5432, "Auto", ],
      [ "opensql2", 5432, "Auto", ],
      [ "opensql3", 5432, "Auto", ],
    ]
    database = "some_db"
    use_patroni = true
    [pools.simple_db]
    pool_mode = "session"
    query_parser_enabled = true
    query_parser_read_write_splitting = true
    primary_reads_enabled = true
    sharding_function = "pg_bigint_hash"
    [pools.simple_db]
    pool_mode = "session"
    default_role = "primary"
    query_parser_enabled = true
    query_parser_read_write_splitting = true
    primary_reads_enabled = true
    sharding_function = "pg_bigint_hash"
    prepared_statements_cache_size = 500
    
    [pools.simple_db.users.0]
    username = "simple_user"
    password = "simple_user"
    pool_size = 5
    statement_timeout = 30000
    
    [pools.simple_db.shards.0]
    servers = [
      [ "opensql1", 5432, "Auto", ],
      [ "opensql2", 5432, "Auto", ],
      [ "opensql3", 5432, "Auto", ],
    ]
    database = "some_db"
    use_patroni = true
    openproxy=> show pools;
      database  |     user      |  pool_mode  | cl_idle | cl_active | cl_waiting | cl_cancel_req | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us 
    ------------+---------------+-------------+---------+-----------+------------+---------------+-----------+---------+---------+-----------+----------+---------+------------
     simple_db  | simple_user   | session     |       0 |         0 |          0 |             0 |         0 |       0 |       0 |         0 |        0 |       0 |          0
    (1 rows)
    
    openproxy=> show databases;
                 name             |    host     | port | database |  force_user   | pool_size | min_pool_size | reserve_pool |  pool_mode  | max_connections | current_connections | paused | disabled 
    ------------------------------+-------------+------+----------+---------------+-----------+---------------+--------------+-------------+-----------------+---------------------+--------+----------
     simple_db_shard_0_replica_0  | 178.176.0.4 | 5432 | some_db  | simple_user   |         5 |             0 |            0 | session     |               5 |                   0 |      0 |        0
     simple_db_shard_0_replica_1  | 178.176.0.2 | 5432 | some_db  | simple_user   |         5 |             0 |            0 | session     |               5 |                   0 |      0 |        0
     simple_db_shard_0_primary    | 178.176.0.3 | 5432 | some_db  | simple_user   |         5 |             0 |            0 | session     |               5 |                   0 |      0 |        0
     (3 rows)
    MEDIAN
    (
      expression  IN { smallint, int, bigint,
                        real, double precision,
                        timestamp, timestamptz, time, timetz, date }
    )
    RETURNS median;
    # Test table
    create table employees (name varchar, salary integer, hire_date timestamptz);
    INSERT INTO employees (name, salary, hire_date) VALUES
    ('John Doe', 55000, '2020-03-15 09:00:00'),
    ('Jane Smith', 62000, '2019-07-22 10:30:00'),
    ('Michael Johnson', 72000, '2018-11-10 08:45:00'),
    ('Emily Davis', 48000, '2021-05-01 12:00:00'),
    ('David Wilson', 53000, '2017-09-17 14:20:00'),
    ('Sarah Brown', 60000, '2016-12-05 09:15:00'),
    ('James Taylor', 75000, '2015-06-30 16:45:00'),
    ('Jessica Martinez', 68000, '2022-01-25 11:10:00'),
    ('Daniel Anderson', 58000, '2020-10-05 13:35:00'),
    ('Laura Thomas', 49500, '2023-08-12 08:00:00');
    
    
    -- Example of calculating the median for integer data
    SELECT oracle.MEDIAN(salary) FROM employees;
    
     median 
    --------
      59000
    (1 row)
    
    
    -- Example of calculating the median for datatype data
    SELECT oracle.MEDIAN(hire_date) FROM employees;
    
             median         
    ------------------------
     2019-11-17 21:45:00+09
    DATE
    CREATE TABLE T (a date);
    INSERT INTO T VALUES ('4713-01-01 01:11:30 BC');
    INSERT INTO T VALUES ('2023-03-19 13:29:30');
    VARCHAR2[(size)]
    EMP_NAME VARCHAR2(10)
    NVARCHAR(size)
    LNNVL
    (
      value  IN boolean
    )
    RETURNS boolean;
    # test 1
    SELECT oracle.LNNVL(true);  
    
     lnnvl 
    -------
     f
    (1 row)
    
    # test 2
    SELECT oracle.LNNVL(false);  
    
     lnnvl 
    -------
     t
    (1 row)
    
    # test 3
    SELECT oracle.LNNVL(NULL);  
    
     lnnvl 
    -------
     t
    (1 row)
    GREATEST
    (
      expr1       IN anynonarray,
      expr_array  IN variadic anyarray
    )
    RETURNS anynonarray;
    # test 1
    SELECT oracle.GREATEST(5, 3, 9);
    
     greatest 
    ----------
            9
    (1 row)
    
    # test 2
    SELECT oracle.GREATEST('apple'::text, 'banana', 'cherry'); -- result: cherry (Compare strings alphabetically)
    
     greatest 
    ----------
     cherry
    (1 row)
    
    # test 3
    SELECT oracle.GREATEST(10, NULL, 7); -- result NULL
    
     greatest 
    ----------
             
    LEAST
    (
      expr1       IN anynonarray,
      expr_array  IN variadic anyarray
    )
    RETURNS anynonarray;
    # test 1
    SELECT oracle.LEAST(5, 3, 9);
    
     least 
    -------
         3
    (1 row)
    
    
    # test 2
    SELECT oracle.LEAST('apple'::text, 'banana', 'cherry'); -- result: apple (Compare strings alphabetically)
    
     least 
    -------
     apple
    (1 row)
    
    # test 3
    SELECT oracle.LEAST(10, NULL, 7); -- result: NULL
    
     least 
    -------
          
    (1 row)
    NANVL
    (
      value         IN { real, double precision, numeric },
      replacement   IN { varchar, real, double precision, numeric }
    )
    RETURNS { real, double precision, numeric };
    # test 1
    SELECT oracle.NANVL(3.14, 0.0); -- result: 3.14 (return the original value as 3.14 is not NaN)
    
     nanvl 
    -------
      3.14
    (1 row)
    
    # test 2
    SELECT oracle.NANVL('NaN'::float4, 0.0); -- result: 0.0 (return the 0.0,replacement value, as 1st value is NaN)
    
     nanvl 
    -------
         0
    (1 row)
    LAST_DAY
    (
      value  IN date
    )
    RETURNS date;
    
    LAST_DAY
    (
      value  IN TIMESTAMP with time zone
    )
    RETURNS TIMESTAMP without time zone;
    -- DATE type example: returns the last day of month that '2023-05-15'belongs to
    SELECT oracle.LAST_DAY('2023-05-15'::date);
    -- result: '2023-05-31' (the last day of May,2023)
    
      last_day  
    ------------
     2023-05-31
    (1 row)
    
    -- TIMESTAMPTZ type example: return the last day of month that '2023-05-15 14:30:00+09'belongs to
    SELECT oracle.LAST_DAY('2023-05-15 14:30:00+09'::timestamptz);
    -- result: The timestamp value is returned with the last day of the month combined with the original time information.
    
          last_day       
    ---------------------
     2023-05-31 14:30:00
    (1 row)
    SYS_EXTRACT_UTC
    (
      time  IN timestamp with time zone
    )
    RETURNS timestamp without time zone;
    
    SYS_EXTRACT_UTC
    (
      time  IN timestamp without time zone
    )
    RETURNS timestamp without time zone;
    # test 1
    SELECT oracle.SYS_EXTRACT_UTC('2023-06-01 12:34:56+07'::timestamptz);
    
       sys_extract_utc   
    ---------------------
     2023-06-01 05:34:56
    (1 row)
    
    # test 2
    -- Convert to timestamptz based on the session time zone '+09:00', then shift to UTC. 
    SELECT oracle.SYS_EXTRACT_UTC('2023-06-01 12:34:56'::timestamp);
    
       sys_extract_utc   
    ---------------------
     2023-06-01 03:34:56
    (1 row)
    TO_MULTI_BYTE
    (
      str  IN text
    )
    RETURNS text;
    SELECT oracle.TO_MULTI_BYTE('Hello, World!');
    
           to_multi_byte        
    ----------------------------
     Hello, World!
    (1 row)
    MONTHS_BETWEEN
    (
      date1  IN date,
      date2  IN date
    )
    RETURNS numeric;
    
    MONTHS_BETWEEN
    (
      timestamptz1  IN timestamptz,
      timestamptz2  IN timestamptz
    )
    RETURNS numeric;
    # test 1
    SELECT oracle.MONTHS_BETWEEN('2023-05-15'::date, '2022-01-10'::date);
    
      months_between  
    ------------------
     16.1612903225806
    (1 row)
    
    # test 2
    SELECT oracle.MONTHS_BETWEEN('2023-05-15 12:00:00+09'::timestamptz, '2022-01-10 08:30:00+09'::timestamptz);
    
      months_between  
    ------------------
     16.1659946143627
    DUMP(expr[, return_fmt [, start_position [, length ] ] ])
    SELECT DUMP('abc'::TEXT, 1016);
                       dump                   
    ------------------------------------------
     Typ=25 Len=3 CharacterSet=UTF8: 61,62,63
    (1 row)
    MOD(num1, num2);
    num1 - num2 * FLOOR(num1/num2)
    SELECT MOD(-11, 4), MOD(11, -4);
     mod | mod 
    -----+-----
      -3 |   3
    RDBMS
  • PostgreSQL

  • OSs and system environments

  • Unix (including Linux)


  • These are the copyright notices for Tmax OpenSQL manual.

    Tmax Tower, 45 Jeongjail-ro, Bundang-gu, Seongnam-si, Gyeonggi-do, Republic of Korea

    Tel : +82-1544-8629

    E-Mail : gitbook@tibero.com

    The contents of this software (Tmax OpenSQL®) manual and the program are protected by copyright laws and international convention. The contents of this manual and the programs described herein are available only under a license agreement with TmaxTibero Co., Ltd. and may be distributed or reproduced only within the scope of the license agreement.

    No part of this document may be transmitted, copied, deployed, or reproduced in any form or by any means, electronic, mechanical, or optical, without the prior written consent of TmaxTibero Co., Ltd. Nothing in this software document and agreement constitutes a transfer of intellectual property rights regardless of whether or not such rights are registered) or any rights to TmaxTibero trademarks, logos, or any other brand features.

    This document is for information purposes only. The company assumes no direct or indirect responsibilities for the contents of this document, and does not guarantee that the information contained in this document satisfies certain legal or commercial conditions. The information contained in this document is subject to change without prior notice due to product upgrades or updates. The company assumes no liability for any errors in this document.

    Tmax OpenSQL® is a registered trademark of TmaxTibero Co., Ltd. All other product and company names are trademarks of their respective owners and are used for reference purposes only.

    Noto is a trademark of Google Inc. Noto fonts are open source. All Noto fonts are published under the SIL Open Font License, version 1.1. (https://www.google.com/get/noto/)

    Some modules or files of this product are subject to the terms of the following licenses.

    • Apache License Version 2.0

    • Apache License Version 1.1

    • Mozilla Public License Version 1.1

    • Berkeley Software Distribution (BSD)

    • MIT License


    The guide contains 4 chapters.

    Describes the configuration of TmaxTibero's OpenSQL

    🔎 Go to Tmax OpenSQL Overview

    Describes how to install an environment of Tmax OpenSQL.

    🔎 Go to Tmax OpenSQL Installation

    Describes how to manage an environment of Tmax OpenSQL.

    🔎 Go to Tmax OpenSQL Administration

    Describes the Tmax O2 Extensions feature, which is an OpenSQL-only extension to TmaxTibero.

    🔎

    Required Knowledge

    This guide is not intended to be all-inclusive of everything you need to know to apply or operate Tmax

    OpenSQL in practice.

    Copyright notice

    Address

    Website

    Technical service center

    Restricted Rights Legend

    Trademarks

    Font Copyrights

    Open Source Software Notice

    Document Organization

    str

    text type; Date/Time string to convert.

    fmt

    text type; Format model that indicates the format of the input string. (ex. 'YYYY-MM-DD HH24:MI:SSOF') For supported format models, refer to the .

    TO_TIMESTAMP_TZ
    (
      str  IN text,
      fmt  IN text
    )
    RETURNS timestamp with time zone;

    Syntax

    Overview

    Parameter

    SELECT oracle.TO_TIMESTAMP_TZ('2023-06-01 12:34:56+09', 'YYYY-MM-DD HH24:MI:SSOF');
    
        to_timestamp_tz     
    ------------------------
     2023-06-01 12:34:56+09
    (1 row)

    Example

    LISTAGG

    Syntax

    LISTAGG
    (
      expression  IN TEXT
    )
    RETURNS text;
    
    LISTAGG
    (
      expression  IN TEXT,
      delimite    IN TEXT
    )
    RETURNS text;

    Overview

    The LISTAGG function is a PostgreSQL implementation extension of Oracle's LISTAGG aggregate function. This function combines multiple text values within a group into a single string and returns it.

    Parameters

    Parameter
    Description

    expression

    text type; the value to aggregate, ignoring it if it is NULL.

    ADD_MONTHS

    Syntax

    ADD_MONTHS
    (
      date    IN,
      number  IN 
    )
    RETURNS date;
    
    ADD_MONTHS
    (
      TIMESTAMP WITH TIME ZONE  IN,
      number                    IN
    )
    RETURNS TIMESTAMP WITHOUT TIME ZONE;

    Overview

    The ADD_MONTHS function returns a new date or timestamp that is the given date or timestamp plus the number of months you specify.

    Internally, it decomposes the input date into years, months, and days, and then adds the total number of months to calculate a new year and month.

    In particular, if the input date is the last day of the current month, it will be adjusted to the last day of the new month.

    If the first argument is timestamptz, it will keep the existing time information after calculating the date.

    Parameters

    Parameter
    Description

    WM_CONCAT

    Syntax

    WM_CONCAT
    (
      expr  IN text
    )
    RETURNS text;

    Overview

    This aggregation function combines multiple text values in a group into a single string. It sequentially combines the input text values to create a single string.

    The inner workings are as follows:

    • If the input value is NULL, exclude it from the aggregation.

    • When the first value is entered, a new state (string buffer) is created.

    • If a value is subsequently entered, the existing string is appended with a default delimiter (comma), followed by the value.

    • When aggregation is complete, the accumulated string is returned as the final result.

    Parameter
    Description

    TO_DATE

    Syntax

    TO_DATE
    (
      str  IN text
    )
    RETURNS timestamp;
    
    TO_DATE
    (
      str  IN text,
      fmt  IN text
    )
    RETURNS timestamp;
    
    TO_DATE
    (
      num  IN integer,
      fmt  IN text
    )
    RETURNS timestamp;

    Overview

    The TO_DATE function converts text (or integer values converted to strings) to TIMESTAMP(0)(date to hours, minutes, and seconds without milliseconds) values in Oracle style date/time format.

    If a format model (FMT) is provided, the date is interpreted according to that format; if not, it is converted according to the default format.

    Returns NULL if an empty string is keyed in.

    Unlike Oracle, it doesn't accept variables of type date to preserve type safety.

    Parameter

    Parameter
    Description

    NUMTODSINTERVAL

    Syntax

    NUMTODSINTERVAL
    (
      number  IN double precision,
      unit    IN text
    )
    RETURNS interval;

    Overview

    The NUMTODSINTERVAL function interprets the given numeric value as a specific unit (e.g., ‘DAY’, ‘HOUR’, ‘MINUTE’, ‘SECOND’) and converts it to the INTERVAL type.

    Numeric values are divided into integer and decimal parts.

    • If 'DAY', the integer part is converted to day and the decimal part is converted to hours, minutes, and seconds by multiplying by 24.

    • If 'HOUR', the integer part is converted to hours and the decimal part is converted to minutes and seconds by multiplying by 60.

    • If 'MINUTE', the integer part is converted to minutes and the decimal part is converted to seconds

      by multiplying by 60.

    • If 'SECOND', the entire number is interpreted as a second

    If an invalid unit is passed, an error occurs.

    Parameter
    Description

    RTRIM

    Syntax

    RTRIM(str [, char_set])

    Overview

    RTRIM is a function that removes all characters contained in char_set from the right side of str.

    Parameter

    Parameter
    Description

    str

    Arbitrary operation that returns a string.

    BITAND

    Syntax

    BITAND(expr1, expr2)

    Overview

    BITAND operations are processed as vectors consisting of inputs and outputs in bits. The output is the result of AND operations performed on the inputs in bits.

    BITAND is calculated through the following steps.

    1. Argument A is replaced by SIGN(A) * FLOOR(ABS(A)).

    2. Argument A is converted to an n-bit two's complement binary integer value. 2-bit values are combined using a bitwise AND operation.

    3. n-bit two's complement value is converted back to NUMBER.

    Parameter
    Description

    LTRIM

    Syntax

    LTRIM(str [, char_set])

    Overview

    LTRIM is a function that removes all characters contained in char_set from the left side of str.

    Parameter

    Parameter
    Description

    str

    Arbitrary operation that returns a string.

    REGEXP_COUNT

    Syntax

    REGEXP_COUNT(str, pattern [, position [, match_param]])

    Overview

    REGEXP_COUNT is a function that returns how many times a pattern given as a regular expression matches within str.

    Parameter

    Parameter
    Description.

    str

    Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    INSTR

    Syntax

    INSTR(string, substring [, position [, occurrence]])

    Ovrview

    INSTR is a function that searches for substring in string. The search operation works by sequentially comparing substrings of the same length as the target substring within the given string to check for a match. The search can proceed either forward or backward, with each new substring starting one character after (or before, in backward search) the previous one. If a matching substring is found, the function returns an integer indicating the position of the first character of the match. If no match is found, it returns 0.

    Parameter

    Parameter
    Description

    string, substring

    LPAD

    Syntax

    LPAD(expr1, num [, expr2])

    Overview

    LPAD is a function that concatenates expr2 to the left of expr1 and returns a string with a length equal to num.

    In most character sets, the number of characters in a returned string is the same as its length, but in multi-byte character sets such as Korean, these two values can differ.

    Parameter

    Parameter
    Description

    expr1

    NLSSORT

    Syntax

    NLSSORT(str [, ' nlsparam '])

    Overview

    NLSSORT is a function that returns the character bytes used to sort str.

    Parameter

    Parameter
    Description

    str

    String value for sorting. It can be TEXT or CHAR type data.

    nls_param

    REGEXP_LIKE

    Syntax

    REGEXP_COUNT(str, pattern [, match_param])

    Overview

    REGEXP_LIKE compares str with the pattern given as a regular expression.

    It follows the POSIX regular expression standard.

    Parameter

    Parameter
    Description

    str

    Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    SUBSTR

    Syntax

    SUBSTR(str, position [, length])

    Overview

    SUBSTR is a function that extracts and returns a string of length length from position position within str.

    Parameter

    Parameter
    Description

    str

    Arbitrary operation that returns a string.

    When values of numeric types such as smallint, integer, bigint, decimal, or numeric are input, they are automatically converted to strings and processed as string values.

    REGEXP_REPLACE

    Syntax

    REGEXP_LIKE(str, pattern [, replace_str [, position [, occurrence [, match_param]]]])

    Overview

    REGEXP_COUNT is a function that searches for a pattern given as a regular expression within str and replaces it with another string.

    Parameter

    Parameter
    Description

    str

    Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    RPAD

    Syntax

    RPAD(expr1, num [, expr2])

    Overview

    RPAD is a function that concatenates expr2 on the right side of expr1 and returns a string with length equal to num.

    In most character sets, the number of characters in the returned string is the same as its length, but in multi-byte character sets such as Korean, the two values may differ.

    Parameter

    Parameter
    Description

    expr1

    REGEXP_SUBSTR

    Syntax

    REGEXP_SUBSTR(str, pattern [, position [, occurrence [, match_param [, subexp]]]])

    Overview

    REGEXP_COUNT is a function that searches for a pattern given as a regular expression within str and returns the corresponding string.

    The type of the result is the same as the type of str.

    Parameter

    Parameter
    Description

    str

    Load balancing

    This document provides a general description of the PostgreSQL server load balancing and query routing features provided by the OpenProxy module in OpenSQL v3.0 and how to configure them.


    In PostgreSQL's Streaming Replication configuration, a non-primary Replica instance can only process Read-Only queries. OpenProxy provides a load-balancing feature that sends read-only queries to one of the Replica instances to process and return results, depending on the configuration.

    By default, OpenProxy manages load balancing options on a per-pool basis (a group of PostgreSQL servers distinguished by their database names when connecting to OpenProxy), and you can assign different settings to different pools.


    To identify and send Read-Only queries to the Replica instance, you must options in the openproxy.toml configuration.

    NVL2

    The NVL2 function returns the value of the second argument if the first argument is non-NULL, and the value of the third argument if the first argument is NULL.

    The second and third arguments must be types of the same category, and there is a separate casts function that performs implicit casting if necessary.

    Parameter
    Description

    NEXT_DAY

    The NEXT_DAY function returns the date of the first specific day of the week that occurs after the given date.

    This function takes a string representing the day of the week (e.g., ‘Monday’, ‘Tue’, etc.) or a day index (1 to 7, where 1 is Sunday) as an argument and processes it.

    For the TIMESTAMP WITH TIME ZONE type, it returns a timestamp value with the original time portion intact after calculating the date.

    Parameter
    Description

    ROUND

    The ROUND function rounds a date or timestamp value according to a given format model.

    In other words, it adjusts the date or time value according to the specified unit (e.g., year, month, minute, etc.) and returns it.

    The format string (fmt) allows you to specify the rounding unit, and if the value is NULL, it will be returned as NULL for the new value.

    For the timestamp version, the seconds are set to zero after rounding up the time portion.

    Parameter

    TO_CHAR

    The TO_CHAR function converts a number, date, timestamp, or string value to a string according to the format model (fmt) specified.

    If no format model is provided, each data type is converted to a string according to its default output format.

    For numeric types, integers, floating point numbers, and numeric values are converted according to the format.

    Dates and timestamps are converted to the specified format (e.g., 'YYYY-MM-DD', 'HH24:MI:SS').

    Parameter
    Description

    UNISTR

    The UNISTR function converts Unicode escape sequences in the input text to actual Unicode characters and returns them.

    The supported escape formats are as follows:

    • \XXXX : 4-digit hexadecimal format

    • \uXXXX : 4-digit hexadecimal format (prefixed with a 'u')

    TRUNC

    The TRUNC function truncates subunits from a date or timestamp value and returns the truncated (discarded) result to fit the specified format model.

    In other words, it removes the decimal part (or detail units) from the time or date part of the value, leaving only the desired units (e.g., year, month, day, etc.).

    If no format string (fmt) is provided, it defaults to 'DDD' (day in days out).

    For the timestamp version, the internal time information is processed together to truncate sub-hour increments, and sub-second information is set to zero.

    NVL

    The NVL function returns the value of the first of the two arguments if it is not NULL, and the value of the second argument if it is NULL.

    Called only for arguments of the same type, but performs an implicit cast if they are of different types. The return type follows the type of the first argument.

    Parameter
    Description

    TO_NUMBER

    The TO_NUMBER function converts the entered string or numeric value to an Oracle-style numeric value.

    If entered as text, it converts the numeric format string to a number after adjusting the decimal and thousands separator characters based on your locale settings.

    Also, type values of smallint, int, bigint anddouble precision are converted to numeric

    types through internal logic specific to each type.

    Input of type numeric

    REGEXP_INSTR

    REGEXP_INSTR is a function that returns the position where the pattern given as a regular expression matches within str.

    If it does not match str, it returns 0.

    Parameter
    Description
    PG official documentation
    Date/time format models

    delimiter

    text type; the delimiter to insert between each text value. If called without a delimiter, the internal

    Example

    date

    date type: represents the date it is based on.

    timestamp with timezone

    timestamptz type: represents the date+ time+timezone.

    number

    integer, double precision, numeric type: represents the number of months to be added and is internally converted to an integer.

    Example

    expr

    text type: the text value to aggregate.

    null values are excluded from aggregation.

    Parameters

    Example

    str

    text type; String containing date and time information. If it is an empty string, it is treated as NULL.

    num

    integer type; Integer value that is internally converted to a string and interpreted as a date.

    fmt

    text type; Format model that specifies the date/time format of the input string.

    For example, use ‘YYYY-MM-DD HH24:MI:SS’.

    For supported format models, refer to the PG official documentation.

    • Date/time format models

    Example

    number

    double precision type; the time value to convert. If there is a decimal part, it is converted to a lower unit (hour, minute, second).

    unit

    text type; It specifies the unit of the numeric value. Valid units are ‘DAY’, ‘HOUR’, ‘MINUTE’, and ‘SECOND’. For example, if ‘DAY’ is specified, the decimal part is converted to hours, minutes, and seconds in that order.

    Parameter

    Example

    char_set

    Arbitrary operation that returns a string. If the value of the char_set parameter is not specified, the default value is one space character.

    Example

    expr1, expr2

    If any of the arguments of an arbitrary operation that returns an integer value is NULL, the result is NULL. Arguments must be within the range -(2^(n-1)) to (2^(n-1) - 1). If the argument is out of range, the result is undefined.* Currently, n is 64.

    Parameter

    Example

    char_set

    Arbitrary operation that returns a string. If the value of the char_set parameter is not specified, the default value is one space character.

    Example

    pattern

    Arbitrary operation that returns a string written as a regular expression. It can be of type TEXT or CHAR.

    position

    Arbitrary operation that returns a numeric value.

    It specifies where to start pattern checking.

    match_param

    Arbitrary operation returning a string. It sets how to check for patterns. The following values can be used, and multiple values can be used simultaneously.

    • i : It is not case sensitive.

    • c : It is case sensitive.

    • n : Periods (.) include line breaks.

    • m : The input string is more than one line.

    • x : This ignores whitespace characters in the pattern.

    Example

    Arbitrary operations that all return strings. If the string substr is not found within the string str, 0 is returned. The position value of the string starts from 1.

    position

    Arbitrary operation that returns a non-zero integer value. (Default: 1) If position is given, search starts from the position of the string str. If position is negative, search starts from the end of the string str.

    occurrence

    Arbitrary operation that returns an integer value other than 0. (Default: 1) Given occurrence, returns the position of substr, which appears occurrence times within the search string. occurrence must be a positive integer.

    Example

    Arbitrary operation expression that returns a string, CLOB type, or BLOB type. If the length of expr1 is greater than num, returns the string from the left side of expr1 that is equal to num.

    expr2

    Arbitrary operation that returns a string, CLOB type, or BLOB type. If expr2 is not specified, a space character is used.

    num

    Arbitrary operation that returns a numeric value. num refers to the length of the output to the terminal.

    Example

    Parameter that defines the character set to be used for sorting str. It can be TEXT or CHAR type data. It can be defined in the format ‘NLS_SORT=sort’. If not defined, the value defined in the session is used.

    Example

    pattern

    Arbitrary operation that returns a string written as a regular expression. Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    match_param

    Arbitrary operation returning a string. It sets how to check for patterns. The following values can be used, and multiple values can be used simultaneously.

    • i : It is not case sensitive.

    • c : It is case sensitive.

    • n : Periods (.) include line breaks.

    • m : The input string is more than one line.

    • x : This ignores whitespace characters in the pattern.

    Example

    position

    Arbitrary operation returning an integer value. If position is less than 0, it is extracted from the end of str.

    length

    Arbitrary operation returning an integer value. If length is not specified, the string is extracted from the position of str to the end. If length is less than 1, returns NULL.

    Example

    pattern

    Arbitrary operation that returns a string written as a regular expression. Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    replace_str

    Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    position

    Arbitrary operation that returns a numeric value.

    It specifies where to start pattern checking.

    occurrence

    Arbitrary operation that returns a numeric value. It specifies how many times to check the pattern.

    match_param

    Arbitrary operation returning a string. It sets how to check for patterns. The following values can be used, and multiple values can be used simultaneously.

    • i : It is not case sensitive.

    • c : It is case sensitive.

    • n : Periods (.) include line breaks.

    • m : The input string is more than one line.

    • x : This ignores whitespace characters in the pattern.

    Example

    Arbitrary operation expression that returns a string, CLOB type, or BLOB type. If the length of expr1 is greater than num, returns the string from the left side of expr1 that is equal to num.

    expr2

    Arbitrary operation that returns a string, CLOB type, or BLOB type. If expr2 is not specified, a space character is used.

    num

    Arbitrary operation that returns a numeric value. num refers to the length of the output to the terminal.

    Example

    Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    pattern

    Arbitrary operation that returns a string written as a regular expression. Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    position

    Arbitrary operation that returns a numeric value.

    It specifies where to start pattern checking.

    occurrence

    Arbitrary operation that returns a numeric value. It specifies how many times to check the pattern.

    match_param

    Arbitrary operation returning a string. It sets how to check for patterns. The following values can be used, and multiple values can be used simultaneously.

    • i : It is not case sensitive.

    • c : It is case sensitive.

    • n : Periods (.) include line breaks.

    • m : The input string is more than one line.

    • x : This ignores whitespace characters in the pattern.

    subexp

    Arbitrary operation that returns a numeric value. It can be used from 0 to 9. subexp assigns numbers to each group enclosed in parentheses in pattern from left to right.

    Example

    query_parser_enabled : Enables the Query Parsing feature. In addition to Read / Write Splitting, you need to enable the corresponding options to utilize the plugin's features.

  • query_parser_read_write_splitting : Enables the Infer feature that determines whether a query can be sent to Replica (Read-Only) or can only be processed by Primary based on the parsed query.

  • Depending on the PostgreSQL configuration of the pool, the OpenProxy operating with the above options will parse the user query and send the user request to the server with the Replica Role for processing.

    • If you are processing SELECT queries with the Simple Query protocol or parsing and processing SELECTs without explicit transaction blocks with the Extended protocol, you can route them to Replica.

    • To process one or multiple statements within an explicit transaction, use the Route to Primary.

    • If you also want to include the Primary node as a target for sending Read-Only queries, enable the

      primary_reads_enabled option as shown below.

    This option also works in session pooling mode (where one client is processed on one PostgreSQL server connection), but because the PostgreSQL server connection obtained as a result of infer() the client's first query is persisted until the client session ends, errors can occur if you process a SELECT query first and then send a query that should be processed only on Primary.

    session 풀링 모드 (하나의 클라이언트가 하나의 PostgreSQL 서버 연결에서 처리되는 방식) 에서도 해당 옵션은 동작하지만 클라이언트의 첫 쿼리를 infer() 한 결과로 얻은 PostgreSQL 서버 연결이 클라이언트 세션 종료시까지 유지되므로, SELECT 쿼리를 먼저 처리하고 이후 Primary에서만 처리되어야 하는 쿼리를 보내는 경우 에러가 발생할 수 있다.

    • If you want to use query parsing and load balancing features, we recommend using transaction pooling mode (where one transaction is processed on one PostgreSQL server connection).

    On a per-pool basis, you can set how you want to select replicas to process read-only queries.

    • The random method selects one of the PostgreSQL servers at random to route the request.

    • The loc method routes requests to the PostgreSQL server with the fewest number of currently active.

    A Prepared Statement is a way of executing queries in the PostgreSQL Extended Protocol that uses a customized query as a precompiled query execution plan that is stored as an object on the DBMS server.

    PostgreSQL supports the creation and processing of Prepared Statements on a per-client session basis.

    In OpenProxy's session pooling mode, a single client is processed on only one PostgreSQL server connection until it terminates, so no action is required, but in transaction pooling mode, a single client can be processed on multiple PostgreSQL server connections per transaction, which can cause problems when processing Prepared Statements.

    • To accomplish this, OpenProxy provides a global Prepared Statement cache when operating in transaction pooling mode.

    • All Prepared Statements declared by Clients are stored in the cache, and when a Client wants to run a Prepared Statement, it fetches the Prepared Statement from the cache and checks whether it has been declared in the current PostgreSQL server session; if not, it declares it before executing it.

    • To enable this global cache, you must specify a value for the Pool's prepared_statements_cache_size. The default value is 0, which disables the global cache.

    • When the global cache is disabled, it only supports processing of Unnamed (unnamed by the client) Prepared Statements within the Client, meaning that if the Client tries to bind and execute more than one Prepared Statement, an error will occur.

    The global cache is maintained in LRU fashion, and if the value is too small, problems may occur when processing client requests that declare many Prepared Statements.


    When Query Parser is enabled in transaction pooling mode, the processing of the following SQL commands is limited.

    PREPARE, EXECUTE

    • This is a command that explicitly creates a Named Prepared Statement at the SQL level and instructs the user to execute it. It does not work in transaction pooling mode because each transaction can run on a different server connection.

    • You can use session pooling mode because the connection between the client and server is the same for the duration of the session.

    Execution of user-defined function

    • If you create a custom function in Database using the CREATE FUNCTION syntax, and the function contains DDL or DML statements that should be executed only on the Primary node, execution of the function using a SELECT query might be routed to the Replica node, depending on the OpenProxy configuration settings, resulting in an error.

    • You can wrap the execution of a specific statement in an explicit Transaction Block BEGIN ... COMMIT to create a Primary. You can bypass the direction to route only to the node.

    Overview

    Features

    Read-Only Load Balancing

    Configuration

    Enable Query Parser

    Load Balancing configuration

    Prepared Statement Cache configuration

    Cautions

    Unsupported features

    The first value to evaluate. If this value is non-NULL, it is the basis for returning the second argument.

    expr2

    The value that will be returned if the first argument is not NULL.

    expr3

    The value that will be returned if the first argument is NULL.

    The types of the second and third arguments must match, and casting is performed if necessary.

    Syntax

    Overview

    Parameters

    expr1

    Example

    value

    date, timestamp type: a date string value to base on.

    weekday

    text type: A string representing the target day of the week to be searched. It follows Oracle's day of the week convention, and only the first three characters of the string are used.

    The first three characters of the string, regardless of case, are as follows "sun", "mon", "tue", "wed", "thu", "fri", "sat"

    weekday_index

    integer type: the index of the day of the week you want to find. Valid values are 1 through 7, where 1 is considered Sunday, 2 is considered Monday, ..., and 7 is considered Saturday.

    Syntax

    Overview

    Parameters

    Example

    Description

    expr

    date, timestamp, timestamptz type: the date or timestamp value to round to.

    fmt

    text type: A format string indicating the rounding criteria. For example, you can round to various units such as ‘YYYY’, ‘MM’, ‘DDD’, ‘HH24’. If this value is NULL, it will be treated as the default, returning the original value, or as 'DDD' (rounded to the nearest day).

    Syntax

    Overview

    Parameters

    Example

    \+XXXXXX : hexadecimal format consisting of six digits following the ‘+’ symbol.

  • \UXXXXXXXX : 8-digit hexadecimal format following the ‘U’ symbol.

  • The function converts to the correct Unicode code points through surrogate pair processing, and raises an error if an invalid surrogate pair is detected.

    Parameter
    Description

    str

    text type; Target text to convert. The Unicode escape sequences within this string are replaced with actual Unicode characters.

    Syntax

    Overview

    Parameter

    Example

    Parameter
    Description

    expr

    date, timestamp, timestamptz type; the target date or timestamp value to truncate. If this value is NULL, the result will also be NULL.

    fmt

    text type;

    A format string that specifies which units the date or timestamp value should be truncated to. For example, you can specify ‘YYYY’ (year), ‘MM’ (month), ‘DDD’ (day), etc.

    If this value is NULL, the default value (e.g., ‘DDD’) is used.

    Syntax

    Overview

    Parameters

    Example

    The first value to evaluate. If this value is not NULL, it is returned as is.

    expr2

    The value to be returned if the first argument is NULL; if the two arguments are of different types, an appropriate cast may be attempted (e.g., from text to number or date).

    Syntax

    Overview

    Parameters

    expr1

    Example

    # test table
    create table employees ( first_name varchar, last_name varchar );
    
    INSERT INTO employees (first_name, last_name) VALUES
    ('John', 'Doe'),
    ('Jane', 'Smith'),
    ('Michael', 'Johnson'),
    ('Emily', 'Davis'),
    ('David', 'Wilson'),
    ('Sarah', 'Brown'),
    ('James', 'Taylor'),
    ('Jessica', 'Martinez'),
    ('Daniel', 'Anderson'),
    ('Laura', 'Thomas');
    
    
    # test 1
    select oracle.listagg(last_name, ',') from employees ;
    
                                   listagg                                
    ----------------------------------------------------------------------
     Doe,Smith,Johnson,Davis,Wilson,Brown,Taylor,Martinez,Anderson,Thomas
    (1 row)
    
    # test 2
    select oracle.listagg(last_name) from employees ;
                               listagg                           
    -------------------------------------------------------------
     DoeSmithJohnsonDavisWilsonBrownTaylorMartinezAndersonThomas
    (1 row)
    # test 1
    select oracle.add_months('2023-01-31'::date, 3);
    
     add_months 
    ------------
     2023-04-30
    (1 row)
    
    # test 2
    select oracle.add_months('2023-01-31'::date, 3.9999);
    
     add_months 
    ------------
     2023-04-30
    (1 row)
    
    # test 3
    SELECT oracle.ADD_MONTHS('2023-01-31 15:30:00+09'::timestamptz, 1);
    
         add_months      
    ---------------------
     2023-02-28 15:30:00
    (1 row)
    
    # test 4
    SELECT oracle.ADD_MONTHS('2023-01-31 15:30:00+09'::timestamptz, 1.3);
    
         add_months      
    ---------------------
     2023-02-28 15:30:00
    (1 row)
    # Test table
    create table employees ( first_name varchar, last_name varchar );
    
    INSERT INTO employees (first_name, last_name) VALUES
    ('John', 'Doe'),
    ('Jane', 'Smith'),
    ('Michael', 'Johnson'),
    ('Emily', 'Davis'),
    ('David', 'Wilson'),
    ('Sarah', 'Brown'),
    ('James', 'Taylor'),
    ('Jessica', 'Martinez'),
    ('Daniel', 'Anderson'),
    ('Laura', 'Thomas');
    
    
    # test 1
    select oracle.wm_concat(last_name) from employees ;
    
                                  wm_concat                               
    ----------------------------------------------------------------------
     Doe,Smith,Johnson,Davis,Wilson,Brown,Taylor,Martinez,Anderson,Thomas
    (1 row)
    
    # test 2
    select oracle.wm_concat(first_name) from employees ;
    
                               wm_concat                            
    ----------------------------------------------------------------
     John,Jane,Michael,Emily,David,Sarah,James,Jessica,Daniel,Laura
    (1 row)
    -- Convert date/time strings to TIMESTAMP using text and format models
    SELECT oracle.TO_DATE('2023-06-01 12:34:56', 'YYYY-MM-DD HH24:MI:SS');
    
           to_date       
    ---------------------
     2023-06-01 12:34:56
    (1 row)
    
    -- Use the default conversion format if only text is passed (empty strings return NULL)
    SELECT oracle.TO_DATE('2023-06-01 12:34:56');
    
           to_date       
    ---------------------
     2023-06-01 12:34:56
    (1 row)
    
    -- Convert integer values to strings and convert them to TIMESTAMP
    SELECT oracle.TO_DATE(20230601, 'YYYYMMDD');
    
           to_date       
    ---------------------
     2023-06-01 00:00:00
    (1 row)
    -- 1.5 DAYS is converted to 1 day of 12 hours.
    SELECT oracle.NUMTODSINTERVAL(1.5, 'DAY');
    
     numtodsinterval 
    -----------------
     1 day 12:00:00
    (1 row)
    
    -- 2.75 HOURS is converted to 2 hours 45 minutes.
    SELECT oracle.NUMTODSINTERVAL(2.75, 'HOUR');
    
     numtodsinterval 
    -----------------
     02:45:00
    (1 row)
    
    -- 30 MINUTE is converted to 30 minutes 0 seconds.
    SELECT oracle.NUMTODSINTERVAL(30, 'MINUTE');
    
     numtodsinterval 
    -----------------
     00:30:00
    (1 row)
    
    -- 90 SECOND returns exactly 90 seconds.
    SELECT oracle.NUMTODSINTERVAL(90, 'SECOND');
    
     numtodsinterval 
    -----------------
     00:01:30
    (1 row)
    SELECT RTRIM('ABCDEFGHIJKLMNOP', 'LMNOP');
        rtrim    
    -------------
     ABCDEFGHIJK
     (1 row)
    SELECT BITAND(6,3);
    
     bitand 
    --------
          2
    SELECT LTRIM('ABCDEFGHIJKLMNOP', 'ABCDEF');
       ltrim    
    ------------
     GHIJKLMNOP
     (1 row)
    SELECT REGEXP_COUNT('abcabcabc','abc', 2);
     regexp_count 
    --------------
                2
    (1 row)
    SELECT INSTR('ABCDEABCDEABCDE', 'CD');
     instr 
    -------
         3
     SELECT LPAD('LPAD', 10, '-=');
        lpad    
    ------------
     -=-=-=LPAD
    (1 row)
    SELECT NAME FROM T ORDER BY NLSSORT(NAME);
     name 
    ------
     BAR
     FOO
    (2 rows)
    SELECT REGEXP_LIKE('Hello World', 'world', 'i');
     regexp_like 
    -------------
     t
    (1 row)
    SELECT SUBSTR('ABCDEFG', 3, 2), SUBSTR('ABCDEFG', -3, 2);
     substr | substr 
    --------+--------
     CD     | EF
    SELECT REGEXP_REPLACE('aaaaaaa','([[:alpha:]])', 'x');
     regexp_replace 
    ----------------
     xxxxxxx
    (1 row)
     SELECT RPAD('RPAD', 10, '-=');
        rpad    
    ------------
     RPAD-=-=-=
    (1 row)
    SELECT REGEXP_COUNT('abcabcabc','abc', 2);
     regexp_count 
    --------------
                2
    (1 row)
    [pools.my_pool]
    pool_mode = "transaction"
    query_parser_enabled = true
    query_parser_read_write_splitting = true
    [pools.my_pool]
    pool_mode = "transaction"
    query_parser_enabled = true
    query_parser_read_write_splitting = true
    primary_reads_enabled = true
    [pools.my_pool]
    load_balancing_mode = "random" ## "random", "loc"
    [pools.my_pool]
    pool_mode = "transaction"
    prepared_statements_cache_size = 1000
    NVL2(expr1, expr2, expr3)
    # test data
    create table employees (
      first_name varchar,
      last_name varchar,
      salary integer,
      hire_date timestamptz,
      commission_pct integer,
      bonus integer,
      status varchar
    );
    
    INSERT INTO employees (first_name, last_name, salary, hire_date, commission_pct, bonus, status) VALUES
    ('John', 'Doe', 55000, '2020-03-15 09:00:00', NULL, 2000, 'Active'),
    ('Jane', 'Smith', 62000, '2019-07-22 10:30:00', 10, 3000, 'Active'),
    ('Michael', 'Johnson', 72000, '2018-11-10 08:45:00', 7, 2500, 'Inactive'),
    ('Emily', 'Davis', 48000, '2021-05-01 12:00:00', NULL, 1500, NULL),
    ('David', 'Wilson', 53000, '2017-09-17 14:20:00', 8, 2200, NULL),
    ('Sarah', 'Brown', 60000, '2016-12-05 09:15:00', 12, 2800, 'Active'),
    ('James', 'Taylor', 75000, '2015-06-30 16:45:00', NULL, 2600, 'Resigned'),
    ('Jessica', 'Martinez', 68000, '2022-01-25 11:10:00', 5, 1800, NULL),
    ('Daniel', 'Anderson', 58000, '2020-10-05 13:35:00', 6, 2000, 'Active'),
    ('Laura', 'Thomas', 49500, '2023-08-12 08:00:00', 4, 1200, 'Probation');
    
    # test 1
    -- return bonus if commission_pct value is not NULL, and 0 if NULL
    SELECT oracle.NVL2(commission_pct, bonus, 0)
    FROM employees;
    
     nvl2 
    ------
        0
     3000
     2500
        0
     2200
     2800
        0
     1800
     2000
     1200
    (10 rows)
    
    # test 2
    -- return the Second argument (e.g., 'Active') If the first argument is not NULL, and the third argument (e.g., 'Inactive') if NULL
    SELECT oracle.NVL2(status, 'Active', 'Inactive')
    FROM employees;
    
    
       nvl2   
    ----------
     Active
     Active
     Active
     Inactive
     Inactive
     Active
     Active
     Inactive
     Active
     Active
    (10 rows)
    NEXT_DAY
    (
      value          IN date,
      weekday        IN text
    )
    RETURNS date;
    
    NEXT_DAY
    (
      value          IN date,
      weekday_index  IN integer
    )
    RETURNS date;
    
    NEXT_DAY
    (
      value          IN TIMESTAMP WITH TIME ZONE,
      weekday        IN text
    )
    RETURNS TIMESTAMP without time zone;
    
    NEXT_DAY
    (
      value          IN TIMESTAMP WITH TIME ZONE,
      weekday_index  IN integer
    )
    RETURNS TIMESTAMP without time zone;
    -- char type day example: returns the first Monday after '2023-05-15' 
    SELECT oracle.NEXT_DAY('2023-05-15'::date, 'Monday');
    
      next_day  
    ------------
     2023-05-22
    (1 row)
    
    -- index based day example : returns the first Monday(index 2) after '2023-05-15' 
    SELECT oracle.NEXT_DAY('2023-05-15'::date, 2);
    
      next_day  
    ------------
     2023-05-22
    (1 row)
    
    -- TIMESTAMP WITH TIME ZONE example (char):
    SELECT oracle.NEXT_DAY('2023-05-15 14:30:00+09'::timestamptz, 'Friday');
    
          next_day       
    ---------------------
     2023-05-19 14:30:00
    (1 row)
    
    -- TIMESTAMP WITH TIME ZONE example (index):
    SELECT oracle.NEXT_DAY('2023-05-15 14:30:00+09'::timestamptz, 6);
    
          next_day       
    ---------------------
     2023-05-19 14:30:00
    (1 row)
    ROUND
    (
      expr  IN date [, fmt   IN text]
    )
    RETURN date;
    
    ROUND
    (
      expr  IN timestamp without time zone [, fmt   IN text]
    )
    RETURN timestamp without time zone;
    
    ROUND
    (
      expr  IN timestamp with time zone [, fmt   IN text]
    )
    RETURN timestamp with time zone;
    # test 1
    -- round date example: rounds the date '2023-05-15' to month
    SELECT oracle.ROUND('2023-05-15'::date, 'MONTH');
    -- result: returns a date adjusted to the start of the month or a specific reference date in the month.
    
       round    
    ------------
     2023-05-01
    (1 row)
    
    # test 2
    -- round date example (unformatted): rounds to the default format('DDD')
    SELECT oracle.ROUND('2023-05-15'::date);
    -- result: returns the result with the date '2023-05-15' rounded according to the format model
    
       round    
    ------------
     2023-05-15
    (1 row)
    
    
    # test 3
    -- round timestamp example: rounds timestamp '2023-05-15 14:35:20' to hours
    SELECT oracle.ROUND('2023-05-15 14:35:20'::timestamp, 'HH24');
    -- result: '2023-05-15 15:00:00' (minutes and seconds are adjusted to 0)
    
            round        
    ---------------------
     2023-05-15 15:00:00
    (1 row)
    
    # test 4
    -- round timestamp with time zone example: rounds to the default format('DDD')
    SELECT oracle.ROUND('2023-05-15 14:35:20+09'::timestamptz);
    -- result: returns the timestamp rounded according to the format model
    
             round          
    ------------------------
     2023-05-16 00:00:00+09
    (1 row)
    UNISTR
    (
      str  IN text
    )
    RETURNS text;
    -- Example using 4-digit hexadecimal Unicode escape (e.g., \0041 is converted to ‘A’)
    SELECT oracle.UNISTR('\0041\0042\0043');
    -- result: 'ABC'
    
     unistr 
    --------
     ABC
    (1 row)
    
    -- Example including escape sequences in various formats
    SELECT oracle.UNISTR('\u0041 \+00420042 \U00000041');
    
      unistr  
    ----------
     A 42 A
    (1 row)
    
    
    select oracle.unistr('\0441\043B\043E\043D');
    
     unistr 
    --------
     слон
    (1 row)
    
    select oracle.unistr('d\u0061t\U00000061');
    
     unistr 
    --------
     data
    (1 row)
    
    -- Example of incorrect format
    SELECT oracle.unistr('wrong: \db99');
    ERROR:  invalid Unicode surrogate pair
    
    SELECT oracle.unistr('wrong: \db99\0061');
    ERROR:  invalid Unicode surrogate pair
    
    SELECT oracle.unistr('wrong: \+00db99\+000061');
    ERROR:  invalid Unicode surrogate pair
    
    SELECT oracle.unistr('wrong: \+2FFFFF');
    ERROR:  invalid Unicode escape value
    
    SELECT oracle.unistr('wrong: \udb99\u0061');
    ERROR:  invalid Unicode surrogate pair
    
    SELECT oracle.unistr('wrong: \U0000db99\U00000061');
    ERROR:  invalid Unicode surrogate pair
    
    SELECT oracle.unistr('wrong: \U002FFFFF');
    ERROR:  invalid Unicode escape value
    TRUNC
    (
      expr  IN date [, fmt   IN text]
    )
    RETURNS date;
    
    TRUNC
    (
      expr  IN timestamp without time zone [, fmt   IN text]
    )
    RETURNS timestamp without time zone;
    
    TRUNC
    (
      expr  IN timestamp with time zone [, fmt   IN text]
    )
    RETURNS timestamp with time zone;
    # test 1
    -- date truncation: truncates '2023-05-15' to the month, returning the first day of the month
    SELECT oracle.TRUNC('2023-05-15'::date, 'MONTH');
    -- result: '2023-05-01'
    
       trunc    
    ------------
     2023-05-01
    (1 row)
    
    # test 2
    -- date truncation: when unformatted, the original date is returned as is.
    SELECT oracle.TRUNC('2023-05-15'::date);
    -- result: '2023-05-15'
    
       trunc    
    ------------
     2023-05-15\q
     
    (1 row)
    
    # test 3
    -- truncate timestamp: truncates '2023-05-15 14:35:20' to hours, removing minutes and seconds
    SELECT oracle.TRUNC('2023-05-15 14:35:20'::timestamp, 'HH24');
    -- result: '2023-05-15 14:00:00'
    
            trunc        
    ---------------------
     2023-05-15 14:00:00
    (1 row)
    
    # test 4
    -- timestamptz truncation: for '2023-05-15 14:35:20+09',if no format is specified, it is truncated to the default format (‘DDD’).
    SELECT oracle.TRUNC('2023-05-15 14:35:20+09'::timestamptz);
    -- result: returns the result with timestamp values truncated (truncated by days)
    
             trunc          
    ------------------------
     2023-05-15 00:00:00+09
    (1 row)
    NVL(expr1, expr2)
    # test data
    create table employees (first_name varchar, last_name varchar, salary integer, hire_date timestamptz);
    
    INSERT INTO employees (first_name, last_name, salary, hire_date) VALUES
    ('John', 'Doe', NULL, '2020-03-15 09:00:00'),
    (NULL, 'Smith', 62000, '2019-07-22 10:30:00'),
    ('Michael', 'Johnson', 72000, '2018-11-10 08:45:00'),
    ('Emily', 'Davis', 48000, '2021-05-01 12:00:00'),
    ('David', 'Wilson', 53000, '2017-09-17 14:20:00'),
    (NULL, 'Brown', NULL, '2016-12-05 09:15:00'),
    ('James', 'Taylor', NULL, '2015-06-30 16:45:00'),
    ('Jessica', 'Martinez', 68000, '2022-01-25 11:10:00'),
    (NULL, 'Anderson', 58000, '2020-10-05 13:35:00'),
    ('Laura', 'Thomas', 49500, '2023-08-12 08:00:00');
    
    
    # test 1
    # return 0 if salary value is NULL; return last_name if first_name value is NULL;
    select oracle.NVL(salary,0), oracle.NVL(first_name, last_name) from employees ;
    
      nvl  |   nvl   
    -------+---------
     55000 | John
     62000 | Jane
     72000 | Michael
     48000 | Emily
     53000 | David
     60000 | Sarah
     75000 | James
     68000 | Jessica
     58000 | Daniel
     49500 | Laura
    (10 rows)
    

    value

    smallint | int | bigint | real | double precision | numeric | text | timestamp | timestamptz The target value to convert. This can be numbers, dates, timestamps, or string values. For text type, the fmt argument is not available, and you must use the mouth Returns the received string as is.

    fmt

    text type; It is a format model that specifies the output format. For example, numbers can be specified as ‘FM9999’, and dates/times can be specified as ‘YYYY-MM-DD HH24:MI:SS’.

    For supported format models, refer to the .

    TO_CHAR
    (
      value IN { smallint | int | bigint | real | double precision | numeric | text | timestamp | timestamptz }
      [, fmt IN text]
    )
    RETURNS text

    Syntax

    Overview

    Parameter

    -- Convert numeric values (without format)
    SELECT oracle.TO_CHAR(12345);
    
     to_char 
    ---------
     12345
    (1 row)
    
    -- Convert numeric values (apply format)
    SELECT oracle.TO_CHAR(12345, 'FM0000000');
    
     to_char 
    ---------
     0012345
    (1 row)
    
    -- Date value conversion (basic format)
    SELECT oracle.TO_CHAR(oracle.SYSDATE());
    
           to_char       
    ---------------------
     2025-03-07 00:57:44
    (1 row)
    
    
    -- Convert date values (apply format)
    SELECT oracle.TO_CHAR(oracle.SYSDATE(), 'DD-MM-YYYY SS:MI:HH24');
    
           to_char       
    ---------------------
     07-03-2025 46:58:00
    (1 row)
    
    -- Timestamp conversion (timestamptz)
    SELECT oracle.TO_CHAR(oracle.SYSTIMESTAMP(), 'YYYY-MM-DD"T"HH24:MI:SS');
    
           to_char       
    ---------------------
     2025-03-06T15:59:30
    (1 row)

    Example

    is returned as is, and if a format model (fmt) is provided, additional conversion formats can be applied using the PG built-in function (pg_catalog.
    to_number
    ).
    Parameter
    Description

    value

    text, smallint, int, bigint, double precision, numeric type; Target value to convert.

    fmt

    numeric type; Format model that specifies the number format to be applied to text input. (ex. '99999.99')

    For supported format models, refer to the .

    TO_NUMBER
    (
      value  IN { text | smallint | int | bigint | double precision | numeric }
    )
    RETURNS numeric;
    
    TO_NUMBER
    (
      value  IN numeric,
      fmt    IN numeric
    )
    RETURNS numeric;

    Syntax

    Overview

    -- Convert text to numeric (default conversion)SELECT oracle.TO_NUMBER('12345.67');
    
     to_number 
    -----------
      12345.67
    (1 row)
    
    -- Convert numeric values using numeric values and numeric value format models
    SELECT oracle.TO_NUMBER(12345.12467, 99999.9);
    
     to_number 
    -----------
       12345.1
    (1 row)
    
    -- Convert integer values to numeric
    SELECT oracle.TO_NUMBER(12345::int);
    
     to_number 
    -----------
         12345
    (1 row)
    
    
    -- Convert double precision values to numeric
    SELECT oracle.TO_NUMBER(12345.67::double precision);
    
     to_number 
    -----------
      12345.67
    (1 row)

    Parameter

    Example

    pattern

    Arbitrary operation that returns a string written as a regular expression. Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    position

    Arbitrary operation that returns a numeric value.

    It specifies where to start pattern checking.

    occurrence

    Arbitrary operation that returns a numeric value. It specifies how many times to check the pattern.

    return_option

    Arbitrary operation that returns a numeric value.

    • 0 : It returns the first position of a string that matches the pattern.

    • 1 : It returns the next position of a string that matches the pattern.

    match_param

    Arbitrary operation returning a string. It sets how to check for patterns. The following values can be used, and multiple values can be used simultaneously.

    • i : It is not case sensitive.

    • c : It is case sensitive.

    sub_expr

    Arbitrary operation that returns a numeric value. It can be used from 0 to 9. sub_expr assigns numbers to each group enclosed in parentheses in pattern from left to right.

    REGEXP_COUNT(str, pattern [, position [, occurrence [, return_option [, match_param [, sub_expr}]]]])

    str

    Syntax

    Overview

    Parameter

    Arbitrary operation that returns a string. It can be of type TEXT or CHAR.

    SELECT REGEXP_INSTR('abcabcabc','abc', 2);
     regexp_instr 
    --------------
                4
    (1 row)

    Example

    Go to Tmax O2 Extentions

    Virtual IP and Redundancy

    Overview

    This document describes the virtual router multiplexing protocol provided by the OpenProxy module in OpenSQL v3.0. (VRRP)-based virtual IP configuration and management features, including how to set up and configure them.

    Virtual IP management features

    • OpenProxy uses the Virtual Router Multiplexing Protocol to perform Virtual IP management.

    • OpenProxy handles virtual router events through a separate asynchronous runtime to avoid impacting PostgreSQL connection pooling and load balancing features.

    • It can also work in a unicast manner by sending advertisement packets to the multicast address of a specified network interface or by setting the IPv4 addresses of other peer nodes (other nodes with OpenProxy configured).

      • Sending/receiving advertisement packets is accomplished by opening a Linux Raw (L3; IP) socket and binding to the network's Multicast address 224.0.0.18 or to the IPv4 address of the node you are running on (if the Unicast option is enabled).

      • Virtual IP acquisition/release is done by opening a Linux Netlink socket and sending RTM_NEWADDR or RTM_DELADDR

    • To enable the virtual IP feature, the OpenProxy process requires the Linux system privilege You need to set cap_net_admin and cap_net_raw.

    • For PostgreSQL clusters configured with Patroni, you can specify that OpenProxy should perform topology discovery via Patroni's REST API without having to define the roles of the PostgreSQL servers to connect to.

      • For each Shard in each Pool, you can enable it by setting the use_patroni (Boolean) key to

        true; if it is not defined, the feature is disabled.


    You can enable the virtual router feature by setting the [general.virtual_router] entry in the OpenProxy configuration file, openproxy.toml.

    Once defined, the virtual router state machine is activated by a separate runtime at the start of the OpenProxy process to handle virtual IP-related events.

    • The interface entry specifies the name of this node's network interface to communicate with other OpenProxy nodes.

    • The router_id entry is an identifier to distinguish the virtual router cluster on this network, with a value between 1 and 255. It must have the same value as the other OpenProxy nodes that will participate in the virtual IP MASTER election.

    • The priority

    In the OpenProxy configuration file, openproxy.toml, enable the topology discovery feature by setting the use_patroni key in the Shard definition in the section where the Pool you want to work with the Patroni REST API is defined.

    • You can set the renew_interval value in the [general] section to adjust how often to update the

      PostgreSQL server's Role by reading the openproxy.toml file or querying the Patroni server.

    • The Port number and Role values are not actually referenced when creating an OpenProxy Connection, but should be entered for backward compatibility.


    To enable the virtual router feature, the OpenProxy process must run as root user or be granted cap_net_raw and cap_net_admin privileges.

    • cap_net_raw is required to open a RAW type network socket.

    • cap_net_admin is required to add/delete Secondary IPs on a network interface.

    Authorize the executable binary openproxy using Linux setcap as shown below.

    If you are executing it as a systemd service, add the options below to grant permissions.

    Patroni

    Describes setting up and running Patroni, an OpenSQL cluster manager.

    Since Patroni needs to run/stop/restart PostgreSQL directly, the PostgreSQL-related parameter settings should be set as a subset of the Patroni configuration settings.

    Patroni has three different types of configurations.

    • These options are stored in the ETCD and applied to all cluster nodes.

    1.0

    • Initial release of O2 Extensions

      • O2Types

      • O2Functions

    n : Periods (.) include line breaks.
  • m : The input string is more than one line.

  • x : This ignores whitespace characters in the pattern.

  • PG official documentation
    Date/Time Format Model
    Number Format Model
    PG official documentation
    Number format models
    O2Views
  • DBMS_ALERT

  • DBMS_OUTPUT

  • DBMS_PIPE

  • DBMS_SQL


    • Improved O2 Common Module functionality: Fixed errors in DBMS_ALERT, DBMS_PIPE, DBMS_OUTPUT, O2Views and some other functions (apply error fixes in bulk for functions with multiple out parameters)


    • Resolved "Failed to open version file" error when viewing O2_EXTENSION_VERSION_INFO view.

    • O2Views: Minor bugfix in create extension initialization function

    • O2Types: Minor bugfix in create extension initialization function


    • Resolved an issue with MONTHS_BETWEEN input argument date values ignoring and incorrectly calculating the presence of hours/minutes/seconds.

    • Resolved server crashes when using the ROUND function.

    • Resolved the session goes down when running the MEDIAN aggregation function, if any of the records to be aggregated contain NULL records.

    • Improved function functionality to handle timestamp type variables as first argument of TO_DATE

      function

    • When TO_TIMESTAMP_TZ function arguments are NULL or ''(empty string), like oracle

      Improved to return null values

    • DBMS_OUTPUT, DBMS_ALERT : resolved errors related to internal transactions for PG14, PG15

      versions


    • Modify DBMS_SQL.BIND ARRAY index parameter range calculation method to align with Oracle

    • Additionally, an error is thrown if a value outside the array range is specified or if it is put into an empty array.

    • Resolved the DBMS_PIPE.NEXT_ITEM_TYPE Result Value Error

    • Improved performance of MEDIAN function and session down when performing function on columns with only NULLs


    • Resolved session crashes when using UTL_FILE

    • Resolved an issue where callstack information from Assert, SIGSEGV, etc. was not properly captured in the log.


    • Improved an issue where calling the new_line(file) interface of the new_line function in the UTL_FILE package without a second argument value would cause the second argument value to have a garbage value and write an unintended number of newlines.

    • Developed feature to detect 'attempting to wait on uncommitted signal from same session' in DBMS_ALERT


    • Resolved an issue where the linesize argument of the fopen function of the UTL_FILE package was omitted, resulting in an unintended error with a memory garbage value when called.

    • UTL_FILE package: Improved internal logic across the board for all functions to ensure that when an argument is omitted, the argument does not have a memory garbage value and cause unintended action.


    • Resolved an issue that oracle.sysdate result was not inserted into the corresponding type column due to incompatibility with the timestamp type caused by changing in the definition of oracle.date type during the uprade from v.1.0.5 to 1.0.6 patch.


    • Resolved an issue that caused the server to crash when the second argument (format) of a TRUNC

      function that takes a date type as an argument was omitted.

    1.0.0

    1.0.1

    Others

    1.0.2

    Troubleshooting

    Others

    1.0.3

    Troubleshooting

    Feature improvements

    Others

    Caution

    O2Functions Extension needs to be regenerated.

    1.0.4

    Troubleshooting

    Others

    Caution

    DBMS_PIPE extension needs to be regenerated.

    1.0.5

    Troubleshooting

    Others

    Caution

    O2Functions and DBMS_OUTPUT extension need to be regenerated.

    1.0.6

    Troubleshooting

    Others

    Caution

    UTL_FILE extension needs to be regenerated.

    1.0.7

    Troubleshooting

    Others

    1.0.8

    Troubleshooting

    Caution

    O2Types extension needs to be regenerated.

    1.0.9

    Troubleshooting

    Caution

    O2Functions extension needs to be regenerated.

    messages directly to the kernel.

    For each shard, you can additionally set the patroni_port variable as needed to set the default

    Port 8008 You can also integrate with Patroni servers that are listening on ports other than the default.

  • When importing a cluster topology in conjunction with a Patroni server, each server in the shard

    must have a port number to connect to PostgreSQL and a PostgreSQL node role (Primary or Replica) is ignored.

  • A Pool set up to work with Patroni sends a request to Patroni's REST API server every set renew_interval (in milliseconds, default: 5000) to get the connection information and Primary/Replica Role information of the PostgreSQL server.

  • HTTP requests to the Patroni server have a timeout of 1 second by default. After sending a request to a server in the shard, if it does not receive a response within the timeout or fails to parse the response, it will send the request to the next server.

    • If all servers are queried and the response is not processed properly, the Role of the server is not updated. This can cause Query Parsing and Read-Write Splitting functions in transaction pooling mode to not work properly.

  • entry is the priority value that this node will have in electing the MASTER virtual router, with a value between 1 and 255. A node with a priority value of 255 will attempt to occupy the virtual IP in the MASTER state rather than the BACKUP state at startup. Otherwise, the node with the highest priority value is recognized through advertisement packets and becomes the MASTER. It is recommended that you set this differently for each node.
  • The advert_int entry is the frequency at which the MASTER node will forward advertisement packets that propagate its status and priority values within the network, measured in seconds, and has a value between 1~ 255. All nodes in the cluster must have the same value, and if the advertisement packet is not received for three consecutive times, the other BACKUP nodes begin to elect the MASTER.

  • vip_addresses is a list of virtual IPs to be occupied by the MASTER node and should be given as a comma- separated list of IPv4 addresses and the bitmask length of the network.

  • pre_promote_script (Optional) is an entry that specifies a command to run on this node when the BACKUP→ MASTER promotion occurs. In certain cloud vendor environments, the node's network interface is virtualized, so registering a virtual IP might require additional work beyond registering the node's Secondary IP.

  • pre_demote_script (Optional) is an entry that specifies the command to run on this node if a MASTER→ BACKUP demote occurs.

  • unicast_peers (Optional) is an option to forward advertisement packets to other OpenProxy nodes in a unicast manner instead of a multicast manner. Specify the IPv4 addresses of other OpenProxy nodes that will participate in the virtual IP MASTER election as a comma-separated array.

  • Patroni integration

    Configuration

    Virtual routers

    Patroni REST API integration

    Execution

    Dynamic configuration can be set using the patronictl edit-config tool or the rest api.

  • Dynamic configuration changes are reflected asynchronously to all nodes.

    • Dynamic reload without restarting patroni after modifying patroni.yml

      • SIGHUP to Patroni process causes local config file to be reread

      • POST /reload REST-API

      • Use Spatronictl reload command

    Some local configuration parameters can be set and overridden with environment variables.

    This manual describes setting up and running with a Local Configuration File of the three methods.

    When the Patroni process is run, it reads the settings from the yaml file located in the path entered as a parameter. You can send a SIGHUP signal to the Patroni process or send a POST /reload request to the REST API server to reload the configuration file. The path to the default template configuration file is /etc/patroni/patroni.yml. Create a yml file in that path and modify the contents of the file to suit your configuration.

    • You can define meta information for Patroni clusters, etcd connection information, logging configuration, REST API server configuration, and PostgreSQL parameter information.

    • PostgreSQL parameters can be set in Local Configuration and Global Dynamic Configuration. If there are duplicate keys, the value in Local Configuration takes precedence.

    • You can define a bootstrap.dcs entry to set the initial configuration set for the Global Dynamic

      Configuration below.

    Create a patroni.yml file for each node as below,

    Change the connect_address value in the REST API part and the hosts setting in etcd3 to the node- specific ip-address address.

    In case of configuring a patroni cluster with the following node addresses

    • node1 172.176.0.2

    • node2 172.176.0.3

    • node3 172.176.0.4

    After creating patroni.yml, execute the patroni process with the command below on each node as shown below. The path to a valid Configuration .yml file must be entered as an argument.

    Use the command,patronictl , to check the cluster is running normally.

    As shown in the example below, the Leader is running and the Replicas are streaming, which is expected during the normal cluster boot state .

    Overview

    Environment configuration

    Global Dynamic Configuration

    Local Configuration File (patroni.yml)

    Environment Variables

    Local Configuration File

    Example of Configuration File

    Execute Patroni

    Check Cluster execution

    [general.virtual_router]
    interface = "eno1"
    router_id = 50
    priority = 150
    advert_int = 3
    vip_addresses = [ "192.168.0.200/24" ]
    pre_promote_script = "/home/opensql/startup.sh"
    pre_demote_script = "/home/opensql/cleanup.sh"
    unicast_peers = [ "192.168.0.7", "192.168.0.8" ]
    [general]
    renew_interval = 5000  ## You can update the Config by reading the openproxy.toml file or query the Patroni server 
                           ## to set the period to update the Role of the PostgreSQL server.
                           ## The unIt IS milliseconds, wIth a default value of 5000.
    
    [pools.my_pool]
    
    [pools.my_pool.shards.0]
    servers = [
      [
        "192.168.0.8",    ## Enter the IPv4 addreSS of the hoStS where the Patroni REST API Server IS runnIng.
    
        5432,             ## Port number to connect to PoStgreSQL, Ignored when connectIng Patroni.
        "Auto",           ## Whether the PostgreSQL InStance haS a Primary / Replica Role IS Ignored when IntegratIng Patroni.
      ],
      [
        "192.168.0.9",
        5432,
        "Auto",
      ],
      [
        "192.168.0.10",
        5432,
        "Auto",
      ]
    ]
    database = "postgres"
    use_patroni = true
    patroni_port = 8765    ## Specifies the port number of the Patroni REST API server. If left blank, the default value 8008 is used.
    $ sudo setcap 'cap_net_raw=eip cap_net_admin=eip' openproxy
    [Service]
    AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN
    scope: opensql
    #namespace: /service/
    name: postgresql0
    postgresql:
      listen: 0.0.0.0:5432
      connect_address: 192.168.0.100:5432
      proxy_address: 127.0.0.1:6432  # The address of connection pool (e.g., pgbouncer) running next to Patroni/Postgres. Only for service discovery.
      #data_dir: data/postgresql0
      data_dir: /var/lib/pgsql/16/data
      bin_dir: /usr/pgsql-16/bin
    #  config_dir:
      pgpass: /tmp/pgpass0
      authentication:
        replication:
          username: patroni_repl
          password: patroni_repl
        superuser:
          username: postgres
          password: zalando
        rewind:  # Has no effect on postgres 10 and lower
          username: patroni_rewind
          password: patroni_rewind
      pg_hba:
        - local all all trust
        - host replication patroni_repl 192.168.0.0/24 trust
        - host replication patroni_repl 127.0.0.1/32 trust
        - host all all 0.0.0.0/0 md5
        - host all barman 192.168.0.0/24 trust
        - host replication streaming_barman 192.168.0.0/24 trust
      parameters:
        log_line_prefix: '%m [%r] [%u] [%a]'
        archive_command: 'barman-wal-archive node4 pg %p'
        archive_mode: 'true'
        wal_level: 'replica'
    # /etc/patroni/patroni.yml
    scope: opensql
    name: postgresql0
    restapi:
      listen: 0.0.0.0:8008
      connect_address: 178.176.0.2:8008
    etcd3:
      protocol: http
      hosts:
      - 178.176.0.2:2379
      - 178.176.0.3:2379
      - 178.176.0.4:2379
      bootstrap:
      # This section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
      # and all other cluster members will use it as a `global configuration`.
      # WARNING! If you want to change any of the parameters that were set up
      # via `bootstrap.dcs` section, please use `patronictl edit-config`!
      dcs:
        ttl: 30
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 1048576
        postgresql:
          use_pg_rewind: true
          parameters:
    #        wal_level: hot_standby
    #        hot_standby: "on"
            max_connections: 100
            max_worker_processes: 8
    #        wal_keep_segments: 8
    #        max_wal_senders: 10
    #        max_replication_slots: 10
    #        max_prepared_transactions: 0
    #        max_locks_per_transaction: 64
    #        wal_log_hints: "on"
    #        track_commit_timestamp: "off"
    #        archive_mode: "on"
    #        archive_timeout: 1800s
    #        archive_command: mkdir -p ../wal_archive && test ! -f ../wal_archive/%f && cp %p ../wal_archive/%f
    #      recovery_conf:
    #        restore_command: cp ../wal_archive/%f %p
    
      # some desired options for 'initdb'
      initdb:  # Note: It needs to be a list (some options need values, others are switches)
      - encoding: UTF8
      - data-checksums
      
      postgresql:
      listen: 0.0.0.0:5432
      proxy_address: 127.0.0.1:6432  # The address of connection pool (e.g.,openproxy) running next to Patroni/Postgres. Only for service discovery.
      data_dir: /home/postgres/data # 
    #  config_dir:
      pgpass: /tmp/pgpass0
      authentication:
        replication:
          username: patroni_repl
          password: patroni_repl
        superuser:
          username: postgres
          password: postgres
        rewind:  # Has no effect on postgres 10 and lower
          username: patroni_rewind
          password: patroni_rewind
      pg_hba:
        - local all all trust
        - host replication replicator all md5
        - host all all all md5
      parameters:
        log_line_prefix: '%m [%r] [%u] [%a]'
    
    tags:
        noloadbalance: false
        clonefrom: false
        nostream: false
    $ patroni /etc/patroni/patroni.yml
    postgres@opensql3:~$ patronictl -c /etc/patroni/patroni.yml list
    + Cluster: cluster (7488929455988801618) ------+----+-----------+
    | Member   | Host        | Role    | State     | TL | Lag in MB |
    +----------+-------------+---------+-----------+----+-----------+
    | patroni1 | 178.176.0.4 | Replica | streaming |  1 |         0 |
    | patroni2 | 178.176.0.2 | Replica | streaming |  1 |         0 |
    | patroni3 | 178.176.0.3 | Leader  | running   |  1 |           |
    +----------+-------------+---------+-----------+----+-----------+

    Prerequisites

    Supported platforms and operating systems

    OpenSQL 3.0 can be installed and operated on the following hardware and operating system environments

    HW/SW
    CPU
    OS
    Binary Bits

    GNU

    x86

    Oracle Linux 8

    Oracle Linux 9

    Rocky Linux 8

    Rocky Linux 9


    To compile and run OpenSQL 3.0, the following system software and library packages must be installed in advance.

    Package name
    Version

    OpenSQL 3.0 recommends a 3-Node, 2-Node configuration to provide high availability, as follows

    This is the classic configuration for high availability, providing redundancy between nodes and automatic failover.

    High availability can also be achieved with a configuration that uses only two nodes, but requires an additional witness node to maintain quorum.

    Item
    Min. specification
    Recommended specification

    Provider
    Type
    vCPUs
    Memory (GB)
    Max. concurrent IOPS
    Disk bandwidth (MB/s)

    This manual provides example configurations of applications that are installed on each node based on a 3-Node configuration. Each server contains the main components required for a cluster configuration and is the foundation for configuring a highly available environment for OpenSQL 3.0.

    Servers
    Components
    IP Address

    clang

    18.1.8

    clang-devel

    18.1.8

    llvm

    18.1.8

    llvm-devel

    18.1.8

    llvm-libs

    18.1.8

    libstdc++-devel

    8.5.0

    zlib

    1.2.11

    readline

    7.0

    gettext

    0.19.8.1

    gettext-libs

    0.19.8.1

    libxslt

    1.1.32

    libicu

    60.3

    libicu-devel

    60.3

    openssl

    1.1.1k

    python3-libs

    3.6.8

    platform-python

    3.6.8

    perl-libs

    5.26.3

    perl-IO-Tty

    1.12

    perl-IPC-Run

    0.99

    Disk type

    SSD

    NVMe SSD

    Disk IOPS

    500 IOPS

    3000 IOPS or more

    Disk bandwidth

    25MB/s

    100MB/s or more

    Disk capacity

    50GB

    100GB or more

    Networks

    1Gbps

    10Gbps or more

    56.25

    GCE

    n1-standard-2 + 50GB PD SSD

    2

    7.5

    1500

    25

    node3

    PostgreSQL, Patorni, etcd, Openproxy

    178.176.0.4

    64bits

    make

    4.2.1

    gcc

    8.5.0

    gcc-c++

    8.5.0

    CPU

    2

    4 core or more

    RAM

    8GB

    AWS

    m4.large

    2

    8

    node1

    PostgreSQL, Patorni, etcd

    178.176.0.2

    node2

    PostgreSQL, Patorni, etcd, Openproxy

    178.176.0.3

    System software requirements

    Standard architecture configuration

    3-Node Configuration

    2-Node Configuration

    Minimum configuration requirements of witness node

    On-promise

    Cloud

    For more information about configuration, you may refer to https://etcd.io/docs/v3.5/op-guide/hardware/

    The above configuration is an example. The actual IP address and deployment configuration can be adjusted based on user's environment.

    3-Node Configuration
    2-Node Configuration

    16 GB or more

    3600

    Etcd

    This section describes how to set up and run etcd, which stores OpenSQL's cluster configuration information and settings.

    Enviroment configuration

    The settings for etcd communication to be installed on the three nodes are mandatory.

    Enviroment configuration etcd.env

    # /etc/etcd/etcd.env 
    # mandatory configuration
    ETCD_NAME=<ETCD_NODE_NAME>
    
    # Initial cluster configuration
    ETCD_INITIAL_CLUSTER=<ETCD_NODE_NAME>=http://<NODE1_IP>:2380,<ETCD_NODE_NAME2>=http://<NODE2_IP>:2380, ...
    ETCD_INITIAL_CLUSTER_STATE=new
    ETCD_INITIAL_CLSUTER_TOKEN=etcd-cluster
    
    # Peer configuration
    ETCD_INITIAL_ADVERTISE_PEER_URLS=http://<NODE_IP>:2380
    ETCD_LISTEN_PEER_URLS=http://<NODE_IP>:2380
    
    # Client/server configuration
    ETCD_ADVERTISE_CLIENT_URLS=http://<NODE_IP>:2379
    ETCD_LISTEN_CLIENT_URLS=http://<NODE_IP>:2379,http://127.0.0.1:2379
    
    #data dir
    ETCD_DATA_DIR=/var/lib/etcd

    Member and cluster information

    Environment Variable
    Example
    Description

    To restrict access to ETCD to users with valid client certificates by issuing TLS certificates and to encrypt end-to-end communication with clients, configure the following items.

    It is divided into [client-server] authentication and [server-server] peer authentication, and the same TLS certificate set can be used in both cases.

    Environment Variable
    Example
    Description

    If you have the following node addresses and are configuring a cluster with etcd nodes

    • node1 172.176.0.2

    • node2 172.176.0.3

    • node3 172.176.0.4


    Register and manage etcd as a systemd service file on each of the three nodes as shown below.

    An example of registering as a Systemd service is shown below. Use the daemon- reload command of the command line tool systemctl to update the configuration with the newly defined etcd.service service definition.

    Once registered, you can enable the service as shown in the example below. Enabled services are automatically started when the system boots.

    Services can be started, stopped, or restarted directly, as shown in the examples below. Even enabled services don't work until explicitly started by a user or rebooted, so run them directly as needed.

    You can check the status of running services as shown in the example below.

    Alternatively, you can also execute it directly from the command line, as shown in the example below.


    Check the status of the etcd cluster on the three nodes by executing the command below.


    Tibero | Enterprise Database CompanyTibero

    TLS authentication

    If necessary, issue a private TLS certificate so that only clients with that TLS certificate can use the ETCD3. You can access the cluster and force it to perform data CRUD.

    cfssl, cfssljson installation

    Modify the Makefile as needed, as shown below.

    Logo

    ETCD_KEY_FILE

    /etc/etcd/pki/node3-key.pem

    Specify the path of the key file to be used for communication between the client and server.

    ETCD_PEER_TRUSTED_CA_FILE

    /etc/etcd/pki/etcd-ca.pem

    This is the signing entity for the TLS certificate used for peer communication between servers, and specifies the root CA certificate path.

    ETCD_PEER_CERT_FILE

    /etc/etcd/pki/node3-peer.pem

    Specify the certificate path to be used for peer communication between servers.

    ETCD_PEER_KEY_FILE

    /etc/etcd/pki/node3-peer-key.pem

    Specify the path of the key file to be used for peer communication between servers.

    ETCD_NAME

    node1

    Specifies the name of a unique node within the ETCD cluster. There must not be more than one node with the same name in the cluster and it must match the node name specified in the section describing cluster information later.

    ETCD_INITIAL_CLUSTER

    node1=http://172.18.0.5:2380,

    node2=http://172.18.0.6:2380,

    node3=http://172.18.0.7:2380

    A list of URLs for communication between peers of ETCD nodes within a cluster separated by commas, used when initializing an ETCD cluster. Must match the ETCD_INITIAL_ADVERTISE_PEER_URLS value defined for each node.

    ETCD_INITIAL_CLUSTER_STATE

    new

    Decides whether to start a new cluster or add this node to an existing cluster. Use new if this is the first node in a new cluster, and existing if this is a new node being added to an existing cluster.

    ETCD_INITIAL_CLUSTER_TOKEN

    my-etcd-cluster

    Nodes with the same token value, which is a unique identifier used for initializing the ETCD cluster, can participate in the cluster.

    ETCD_INITIAL_ADVERTISE_PEER_URLS

    http://172.18.0.5:2380

    A list of peer URLs of this node that are to be made public (advertised) to other nodes in order to communicate between ETCD nodes. A URL must be specified so that other nodes can access this node.

    ETCD_LISTEN_PEER_URLS

    http://172.18.0.5:2380

    A list of URLs that this node's ETCD server will listen to for peer-to-peer communication.

    ETCD_LISTEN_CLIENT_URLS

    http://172.18.0.5:2379,

    https://192.168.0.31:2379,

    http://127.0.0.1:2379

    A list of URLs that this node's ETCD server will listen to for peer-to-peer communication.

    ETCD_ADVERTISE_CLIENT_URLS

    https://192.168.0.31:2379

    A list of server URLs for this node to be advertised to clients. When cluster member information is retrieved using the ETCD API, this value is displayed as Client Addrs.

    ETCD_DATA_DIR

    /var/lib/etcd

    ETCD's data directory

    ETCD_TRUSTED_CA_FILE

    /etc/etcd/pki/etcd-ca.pem

    This is the signing entity for TLS certificates used for communication between clients and servers, and specifies the certificate path of the root CA (certification authority).

    ETCD_CERT_FILE

    /etc/etcd/pki/node3.pem

    Specifies the certificate path to be used for communication between the client and server.

    TLS authentication

    Example etcd preferences for a 3-node cluster

    Execution

    Execute etcd with Systemd

    Execute etcd with Command

    Note

    Etcd is recommended to be registered as Systemd.

    Verification of configuration

    On this example, the name template is changed for the .pem file that is generated by exporting with the cfssljson command for ease of file management.

    Modify the certificate CSR (Certificate Signing Request) as needed, as shown below.

    • Delete the "CN" entry. The Python gRPC gateway that Patroni currently uses as a client to access ETCDs does not support certificates with TLS Common Name applied.

    • In the host entry, enter the IP address and hostname (if necessary) of the ETCD cluster to be configured as an array.

    Modify the certificate authority (CA) CSR as needed, as shown below.

    • Delete “CN” entry.

    • Modify the names entry as needed, as shown below.

    Execute make to generate the certificate.

    • The values of the infra0, infra1, and infra2 environment variables you set are used as file names for the generated .pem certificate.


    • When executing ETCD, set up https connection and certificate through environment variable file /etc/etcd/etcd.env or command line arguments. Only clients with certificates signed using the certificate authority (CA) certificates etcd-ca, etcd-ca-key that you created can access this ETCD instance.

    Change ADVERTISE_CLIENT_URLS, LISTEN_CLIENT_URLS via command line arguments when running /etc/etcd/etcd.env file or ETCD

    • http://127.0.0.1:2379 is for use in a local environment and can be deleted if not needed.

    • The #Certs entry registers the certificates issued through the above process. The peer is utilized for the client and the rest for the server-side TLS certificates.

      • ETCD_TRUSTED_CA_FILE : Path to the certificate authority (CA) certificate for the TLS certificate that the server will trust. If a valid certificate is configured, the ETCD server will validate the certificate for all clients. If you are utilizing client authentication without setting up a separate certificate authority, you should utilize the ETCD_CLIENT_CERT_AUTH=true option.

      • ETCD_CERT_FILE : Path to the TLS certificate to be used for Client - Sever communication.

      • ETCD_KEY_FILE : TLS Key path to be used for Client - Server communication.

      • ETCD_PEER_TRUSTED_CA_FILE : Path to the certificate authority (CA) certificate of the TLS

        for ETCD peer-to-peer communication.

      • ETCD_PEER_CERT_FILE : Path to the TLS certificate to be used for communication between ETCD

        peers.

      • ETCD_PEER_KEY_FILE : TLS Key path to be used for communication between ETCD Peers.

    Overview

    Create a certificate

    Install the necessary tools

    Issue a certificate

    Note

    Refer to the Certificate Issuance Example for ETCD3 Clusters.

    https://github.com/etcd-io/etcd/tree/main/hack/tls-setup

    ETCD integration

    #/etc/etcd/etcd.env
    ## Name the etcd node for this server as node1 
    ETCD_NAME=node1
    
    ## set the names of all etcd nodes in the cluster and their accessible peer URLs
    ETCD_INITIAL_CLUSTER=node1=http://172.176.0.2:2380,node2=http://172.176.0.3:2380,node3=http://172.176.0.4:2380
    ETCD_INITIAL_CLSUTER_TOKEN=etcd-cluster1
    ## In the initial cluster configuration, all 3 nodes are set to 'new' and working. Later modified to
    existing.
    ETCD_INITIAL_CLUSTER_STATE=new
    
    ## Specifies the peer URLs used to communicate between etcd nodes. The default port is 2380
    ETCD_INITIAL_ADVERTISE_PEER_URLS=http://172.176.0.2:2380
    ETCD_LISTEN_PEER_URLS=http://172.176.0.2:2380
    
    # Client/server configuration
    ETCD_ADVERTISE_CLIENT_URLS=http://172.176.0.2:2379
    ETCD_LISTEN_CLIENT_URLS=http://172.176.0.2:2379,http://127.0.0.1:2379
    
    # data dir
    ETCD_DATA_DIR=/var/lib/etcd
    $ sudo vim /usr/lib/systemd/system/etcd.service
    
    [Unit]
    Description=etcd
    Documentation=https://github.com/coreos/etcd
    Conflicts=etcd-member.service
    Conflicts=etcd2.service
    
    [Service]
    EnvironmentFile=/etc/etcd/etcd.env
    ExecStart=/usr/bin/etcd
    Type=notify
    TimeoutStartSec=0
    Restart=on-failure
    RestartSec=5s
    LimitNOFILE=65536
    Nice=-10
    IOSchedulingClass=best-effort
    IOSchedulingPriority=2
    MemoryLow=200M
    
    [Install]
    WantedBy=multi-user.target
    $ sudo systemctl daemon-reload
    $ sudo systemctl enable etcd.service
    Created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /usr/lib/systemd/system/etcd.service.
    $ sudo systemctl start etcd.service
    
    ## Example of stopping the service
    $ sudo systemctl stop etcd.service
    
    ## Example of restarting the service
    $ sudo systemctl restart etcd.service
    $ sudo systemctl status -l etcd
    ● etcd.service - etcd
       Loaded: loaded (/usr/lib/systemd/system/etcd.service; enabled; vendor preset: disabled)
       Active: active (running) since Mon 2025-03-17 16:49:45 KST; 3 weeks 2 days ago
         Docs: https://github.com/coreos/etcd
     Main PID: 4763 (etcd)
       CGroup: /system.slice/etcd.service
               └─4763 /usr/bin/etcd
    
    Apr 09 17:46:30 node2 etcd[4763]: {"level":"warn","ts":"2025-04-09T17:46:30.542+0900","caller":"etcdserver/util.go:170","msg":"apply request took too long","took":"402.056395ms","expected-duration":"100ms","prefix":"read-only range ","request":"key:\"/service/opensql/\" range_end:\"/service/opensql\" ","response":"range_response_count:9 size:6173"}
    $ etcd --name 'node1' \
        --data-dir '/var/lib/etcd' \
        --initial-cluster 'node1=http://172.18.0.2:2380,node2=http://172.18.0.3:2380,node3=http://172.18.0.4:2380' \
        --initial-cluster-token 'etcd-cluster1'
        --initial-cluster-state 'new'
    $ etcdctl member list -w=table
    +------------------+---------+-------+----------------------+-------------------------+------------+
    |        ID        | STATUS  | NAME  |      PEER ADDRS      |      CLIENT ADDRS       | IS LEARNER |
    +------------------+---------+-------+----------------------+-------------------------+------------+
    | bfac432fd36a61d5 | started | etcd3 | http://opensql3:2380 | http://178.176.0.3:2379 |      false |
    | c41cad57348d886f | started | etcd2 | http://opensql2:2380 | http://178.176.0.2:2379 |      false |
    | dc3ff6e1d56a1012 | started | etcd1 | http://opensql1:2380 | http://178.176.0.4:2379 |      false |
    +------------------+---------+-------+----------------------+-------------------------+------------+
    #!/bin/bash
    CFSSL_VERSION=1.6.5
    CFSSL_PATH=/usr/local/bin
    ARCH=amd64
    
    curl -L "https://github.com/cloudflare/cfssl/releases/download/v${CFSSL_VERSION}/cfssl_${CFSSL_VERSION}_linux_${ARCH}" -o cfssl
    curl -L "https://github.com/cloudflare/cfssl/releases/download/v${CFSSL_VERSION}/cfssljson_${CFSSL_VERSION}_linux_${ARCH}" -o cfssljson
    curl -L "https://github.com/cloudflare/cfssl/releases/download/v${CFSSL_VERSION}/cfssl-certinfo_${CFSSL_VERSION}_linux_${ARCH}" -o cfssl-certinfo
    
    chmod +x cfssl cfssljson cfssl-certinfo
    sudo cp cfssl cfssljson cfssl-certinfo ${CFSSL_PATH}/
    $ vim Makefile
    .PHONY: cfssl ca req clean
    
    CFSSL   = @env PATH=$(GOPATH)/bin:$(PATH) cfssl
    JSON    = env PATH=$(GOPATH)/bin:$(PATH) cfssljson
    
    all:  ca req
    
    cfssl:
            HTTPS_PROXY=127.0.0.1:12639 go get -u -tags nopkcs11 github.com/cloudflare/cfssl/cmd/cfssl
            HTTPS_PROXY=127.0.0.1:12639 go get -u github.com/cloudflare/cfssl/cmd/cfssljson
            HTTPS_PROXY=127.0.0.1:12639 go get -u github.com/mattn/goreman
    
    ca:
            mkdir -p certs
            $(CFSSL) gencert -initca config/ca-csr.json | $(JSON) -bare certs/etcd-ca
    
    req:
            $(CFSSL) gencert \
              -ca certs/etcd-ca.pem \
              -ca-key certs/etcd-ca-key.pem \
              -config config/ca-config.json \
              config/req-csr.json | $(JSON) -bare certs/${infra0}
            $(CFSSL) gencert \
              -ca certs/etcd-ca.pem \
              -ca-key certs/etcd-ca-key.pem \
              -config config/ca-config.json \
              config/req-csr.json | $(JSON) -bare certs/${infra1}
            $(CFSSL) gencert \
              -ca certs/etcd-ca.pem \
              -ca-key certs/etcd-ca-key.pem \
              -config config/ca-config.json \
              config/req-csr.json | $(JSON) -bare certs/${infra2}
            $(CFSSL) gencert \
              -ca certs/etcd-ca.pem \
              -ca-key certs/etcd-ca-key.pem \
              -config config/ca-config.json \
              config/req-csr.json | $(JSON) -bare certs/${infra0}-peer
            $(CFSSL) gencert \
              -ca certs/etcd-ca.pem \
              -ca-key certs/etcd-ca-key.pem \
              -config config/ca-config.json \
              config/req-csr.json | $(JSON) -bare certs/${infra1}-peer
            $(CFSSL) gencert \
              -ca certs/etcd-ca.pem \
              -ca-key certs/etcd-ca-key.pem \
              -config config/ca-config.json \
              config/req-csr.json | $(JSON) -bare certs/${infra2}-peer
    
    clean:
            rm -rf certs
    $ vim config/req-csr.json
    {
      "CN": "etcd",               # Delete the Patroni -> etcd connection if you have an encrypted configuration
      "hosts": [
        "localhost",
        "127.0.0.1",
        "node1",
        "node2",
        "node3",
        "172.176.0.2",
        "172.176.0.3",
        "172.176.0.4"
      ],
      "key": {
        "algo": "ecdsa",
        "size": 384
      },
      "names": [
        {
          "O": "autogenerated",
          "OU": "etcd cluster",
          "L": "the internet"
        }
      ]
    }
    $ vim config/ca-csr.json
    {
      "CN": "Autogenerated CA",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "O": "TmaxTibero",
          "OU": "OpenSQL",
          "L": "Seongnam-si",
          "ST": "Gyeonggi-do",
          "C": "KR"
        }
      ]
    }
    $ infra0=node1 infra1=node2 infra2=node3 make
    $ ls -l
    total 84
    -rw-r--r-- 1 yhyjeon yhyjeon  985  1월  6 18:10 etcd-ca.csr
    -rw------- 1 yhyjeon yhyjeon 1679  1월  6 18:10 etcd-ca-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1281  1월  6 18:10 etcd-ca.pem
    -rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node1.csr
    -rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node1-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node1.pem
    -rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node2.csr
    -rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node2-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node2.pem
    -rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node3.csr
    -rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node3-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node3.pem
    -rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node1-peer.csr
    -rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node1-peer-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node1-peer.pem
    -rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node2-peer.csr
    -rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node2-peer-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node2-peer.pem
    -rw-r--r-- 1 yhyjeon yhyjeon  623  1월  6 18:10 node3-peer.csr
    -rw------- 1 yhyjeon yhyjeon  288  1월  6 18:10 node3-peer-key.pem
    -rw-rw-r-- 1 yhyjeon yhyjeon 1196  1월  6 18:10 node3-peer.pem
    $ vim /etc/etcd/etcd.env
    #/etc/etcd/etcd.env
    ## Add the following to register the certificate authority and public and private keys of the certificates to be allowed.
    ## The located .pem certificate is a file that the user who will start the etcd process has read permission to read.
    #Cert
    ETCD_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
    ETCD_CERT_FILE=/etc/etcd/pki/node3.pem
    ETCD_KEY_FILE=/etc/etcd/pki/node3-key.pem
    ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
    ETCD_PEER_CERT_FILE=/etc/etcd/pki/node3-peer.pem
    ETCD_PEER_KEY_FILE=/etc/etcd/pki/node3-peer-key.pem
    #/etc/etcd/etcd.env
    # ...
    ETCD_ADVERTISE_CLIENT_URLS=https://172.18.0.2:2379
    ETCD_LISTEN_CLIENT_URLS=https://172.18.0.2:2379,http://127.0.0.1:2379
    # ...
    #Certs
    ETCD_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
    ETCD_CERT_FILE=/etc/etcd/pki/node1.pem
    ETCD_KEY_FILE=/etc/etcd/pki/node1-key.pem
    ETCD_PEER_TRUSTED_CA_FILE=/etc/etcd/pki/etcd-ca.pem
    ETCD_PEER_CERT_FILE=/etc/etcd/pki/node1-peer.pem
    ETCD_PEER_KEY_FILE=/etc/etcd/pki/node1-peer-key.pem

    O2 Extension Installation

    O2 is a PostgreSQL extension that improves user convenience by providing an interface that is compatible with functions/packages/types supported by Oracle in the PostgreSQL environment.

    System requirements

    Follows the operating system/hardware specifications supported by OpenSQL.


    Overview

    O2 Extension offers two installation methods for installing the product, including

    • Install with the make method

    • Install with the shell method

    The O2 installation file collection directory, which will be enclosed inside the OpenSQL installation package, is in the following format. Inside, there are two installation files (Makefile and install.sh).

    On Linux platforms with PostgreSQL installed, the O2 Extension can be installed automatically via the make command.

    There are two types of installations: a full installation, which installs all extensions that include the O2 Extension at the same time, and individual installations, which install individual extensions.

    PostgreSQL must be installed and the make and pg_config commands must be available on the terminal command line.

    Navigate to the directory where the O2 Extension installation components are gathered (the directory where the Makefile is located) and execute the make command below.

    A individual installation is done by adding the name of the extension you want to install as an argument to the make command.

    • DBMS_ALERT

    • DBMS_OUTPUT

    • DBMS_PIPE

    • DBMS_RANDOM


    In environments where the make command is not available, you can install manually using a shell script.

    You can install the O2 Extension manually on Linux platforms with PostgreSQL installed. You can install the O2 Extension in two ways: a full installation, which installs all the extensions that the O2 Extension includes at the same time, or an individual installation, which installs the individual extensions.

    PostgreSQL must be installed and the pg_config binary must be available on the terminal command line.

    Execute the install.sh script included in the directory (o2) where the O2 Extension installation components are located.

    A individual installation is done by adding the name of the extension you want to install as an argument to the make command.

    • DBMS_ALERT

    • DBMS_OUTPUT

    • DBMS_PIPE

    • DBMS_RANDOM


    Both make/shell installation methods require that you perform the installation with an account where pg_config is available. Verify that the value of the $PATH variable contains /usr/pgsql-{PGversion}/bin .

    You will need to bypass the $PATH and proceed with the installation as the user with the set permissions. Execute the following commands with sudo privileges.


    O2 extensions are categorized into four main groups as follows: The sublists within each group list the names of the individual extensions that are actually available.

    • Types Extension

      • O2Types

    • Views Extension

    Each extension consists of the following files, which can be created separately for each extension.

    Ex) The configuration file for the O2Functions Extension is shown below.

    • Shared object file (eg. o2functions.so)

    • Control file (eg. o2functions.control)

    • Script file (eg. o2functions—1.0.sql, o2functions—1.0—1.1.sql, …)

    And there's a VERSION.json file that organizes the version information for extensions into one place.

    To activate the O2 Extension after installing it, you need to execute the SQL command like below.

    The WITH SCHEMA clause allows you to specify the schema in which the objects defined by the extension will be created; otherwise, the default schema specified in the extension's control file will be used.

    However, it is not available to specify the default schema for Package Extension (DBMS_ALERT, DBMS_PIPE, etc.).


    To update the O2 Extension to a higher version, you need to execute the SQL command like below.


    In HA configurations, you must manually attach to each node to install and update the O2 Extension. Ensure that the O2 Extension version installed on each node matches.

    When a version difference occurs between nodes, the difference in behavior between versions causes a difference in which node the query was sent to when it was performed.

    DBMS_SQL

  • UTL_FILE

  • O2Functions

  • O2Types

  • O2Views

  • DBMS_SQL

  • UTL_FILE

  • O2Functions

  • O2Types

  • O2Views

  • O2Views
  • Functions Extension

    • O2Functions

  • Package Extensions

    • DBMS_ALERT

    • DBMS_OUTPUT

    • DBMS_PIPE

    • DBMS_RANDOM

    • DBMS_SQL

    • UTL_FILE

  • O2 installation file directory structure

    Installation with make method

    Pre-installation requirements

    Full installation

    Individual installations

    List of individual installation extension names

    Installation with shell method

    Pre-installation requirements

    Full installation

    Individual installation

    List of individual installation extension names

    Precaution with installation

    Configuration of pg_config and $PATH

    Method to install from a user account without PGpath set in the $PATH value

    Installation components

    Extension type

    Extension components

    Activate O2 Extension

    Update O2 Extension

    Precautions for HA configuration

    ls -rlta
    
    total 60
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 utl_file
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 o2views
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 o2types
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 o2functions
    -rw-r--r--  1 root root 3266 Mar 13 05:09 install.sh        # script for sh installation 
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 dbms_sql
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 dbms_random
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 dbms_pipe
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 dbms_output
    drwxr-xr-x  2 root root 4096 Mar 13 05:09 dbms_alert
    -rw-r--r--  1 root root 1465 Mar 13 05:09 VERSION.json      # o2 extensions ver. information
    -rw-r--r--  1 root root  672 Mar 13 05:09 Makefile          # Installation file for the make method
    drwxr-xr-x 12 root root 4096 Mar 13 05:09 .
    drwxr-xr-x  6 root root 4096 Mar 13 05:09 ..
    cd o2
    make all # o2 extensions  full installation
    
    # Below is an example log that is output during the entire installation process
    make[1]: Entering directory '/home/opensql/o2/build/o2-dist-1.0.1/o2functions'
    /usr/bin/mkdir -p '/home/opensql/postgres/build/16/lib'
    /usr/bin/mkdir -p '/home/opensql/postgres/build/16/share/extension'
    /usr/bin/mkdir -p '/home/opensql/postgres/build/16/share/extension'
    /usr/bin/install -c -m 755  o2functions.so '/home/opensql/postgres/build/16/lib/o2functions.so'
    /usr/bin/install -c -m 644 .//o2functions.control '/home/opensql/postgres/build/16/share/extension/'
    /usr/bin/install -c -m 644 .//VERSION.json .//o2functions--1.0.sql  '/home/opensql/postgres/build/16/share/extension/'
    make[1]: Leaving directory '/home/opensql/o2/build/o2-dist-1.0.1/o2functions'
    ...
    cd o2
    # make [ extension1 extension2 ... ]
    make o2functions o2types dbms_output
    
    # Below is an example log from a make execution
    make -C o2functions install
    make[1]: Entering directory '/home/opensql/o2/build/o2-dist-1.0.1/o2functions'
    /usr/bin/mkdir -p '/home/opensql/postgres/build/16/lib'
    /usr/bin/mkdir -p '/home/opensql/postgres/build/16/share/extension'
    /usr/bin/mkdir -p '/home/opensql/postgres/build/16/share/extension'
    /usr/bin/install -c -m 755  o2functions.so '/home/opensql/postgres/build/16/lib/o2functions.so'
    /usr/bin/install -c -m 644 .//o2functions.control '/home/opensql/postgres/build/16/share/extension/'
    /usr/bin/install -c -m 644 .//VERSION.json .//o2functions--1.0.sql  '/home/opensql/postgres/build/16/share/extension/'
    make[1]: Leaving directory '/home/opensql/o2/build/o2-dist-1.0.1/o2functions'
    ...
    cd o2
    sh install.sh
    
    # Below is an example log that is output during the entire installation process
    Installing extensions to:
      Library directory: /home/opensql/postgres/build/16/lib
      Shared extension directory: /home/opensql/postgres/build/16/share/extension
    No extension names provided. Scanning ./extensions/ for valid extensions...
    Extensions to install: o2checks dbms_alert dbms_output dbms_pipe dbms_random dbms_sql o2functions o2packages o2types utl_file o2views
    Installing extension: o2checks
      Skipped installing o2checks; This is the internal test framework.
    Installing extension: dbms_alert
      Copied control file: ./dbms_alert.control
      Copied SQL file: ./dbms_alert--1.0.sql
      Copied shared library: ./extensions/dbms_alert/dbms_alert.so
    ...
    Copied METADATA: VERSION.json
    Installation completed.
    # sh install.sh [ extension1 extension2 ... ]
    sh install.sh o2functions o2types dbms_output
    
    # Below is an example log that is output during an individual inSstallation
    Installing extensions to:
      Library directory: /home/opensql/postgres/build/16/lib
      Shared extension directory: /home/opensql/postgres/build/16/share/extension
    Extensions to install: o2functions o2types dbms_output
    Installing extension: o2functions
      Copied control file: ./o2functions.control
      Copied SQL file: ./o2functions--1.0.sql
      Copied shared library: ./extensions/functions/o2functions.so
    Installing extension: o2types
      Copied control file: ./o2types.control
      Copied SQL file: ./o2types--1.0.sql
      Copied shared library: ./extensions/types/o2types.so
    Installing extension: dbms_output
      Copied control file: ./dbms_output.control
      Copied SQL file: ./dbms_output--1.0.sql
      Copied shared library: ./extensions/dbms_output/dbms_output.so
    Copied METADATA: VERSION.json
    Installation completed.
    [root@20fec5585ddd /]# echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/pgsql-16/bin/
    
    # If the path doeS not exISt in $PATH for the account you are currently logged Into, add the path approprIate for the PG verSIon to the $PATH path
    [root@20fec5585ddd /]# echo "export PATH=$PATH:/usr/pgsql-16/bin/" >> ~/.bashrc
    [root@20fec5585ddd /]# source ~/.bashrc
    sudo -u {another USER with PGpath Set to $PATH} bash -l -c "{command to install make or shell}"
    
    # 예시)
    # If the path, /usr/pgsql-16/bin/, is registered in the $PATH of postgres user
    # and to install o2 accessing user, opensql, by the make method
    [opensql@20fec5585ddd /]# sudo -u postgres bash -l -c "make all"
    CREATE EXTENSION {extension name} [WITH SCHEMA {default schema}];
    ALTER EXTENSION {extension name} UPDATE TO {new version};

    View

    This view outputs the version information for each O2 extension and O2 and when it was updated.

    Column
    Type
    Description

    O2_MEMORY_CONTEXT_INFO is a view that provides memory context information used by O2.
    Column
    Type
    Description

    NAME

    TEXT

    The name of the memory context.

    IDENT

    TEXT

    Additional expression identifier information for that context.


    O2_SHARED_MEMORY_INFO is a view that shows SHARED MEMORY usage.

    Column
    Type
    Description

    KEY

    TEXT

    The identifier of the shared memory segment

    USAGE

    INTEGER

    Usage


    DUAL tables can be used in SELECT statements that do not reference another table, and are useful when you need to return at least one row. Selecting from a DUAL table is useful when you use a SELECT statement to calculate a constant expression. Because there is only one row in a DUAL table, the constant value is returned only once.

    Column
    Type
    Description

    DUMMY

    TEXT

    'X'


    DBA_TAB_COLUMNS shows the columns of all tables and views in the database.

    Column
    Type
    Description

    TABLE_NAME

    TEXT

    The names of the tables and views.

    COLUMN_NAME

    TEXT

    The name of the column.


    DBA_TABLES shows all tables in the database.

    Column
    Type
    Description

    TABLE_NAME

    TEXT

    Table name


    DBA_CONS_COLUMNS shows all constrained columns in the database.

    Column
    Type
    Description

    CONSTRAINT_NAME

    TEXT

    The name of the constraint.

    COLUMN_NAME

    TEXT

    The name of the column


    DBA_CONSTRAINTS shows all constraint definitions for all tables in the database.

    Column
    Type
    Description

    CONSTRAINT_NAME

    TEXT

    The name of the constraint.

    INDEX_NAME

    TEXT

    The name of index


    PRODUCT_COMPONENT_VERSION is a view of the version and status for a component product.

    Column
    Type
    Description

    PRODUCT

    TEXT

    The name of the component

    VERSION

    TEXT

    Version


    DBA_OBJECTS is a view of all objects in the database.

    Column
    Type
    Description

    OBJECT_NAME

    TEXT

    오브젝트 이름이다.

    SUBJECT_NAME

    TEXT

    하위 객체 이름이다. 호환성을 위해 추가된 컬럼이다.(Default : NULL)


    DBA_PROCEDURES shows all available functions and procedures with their associated properties.

    Column
    Type
    Description

    OBJECT_NAME

    TEST

    The name of object


    DBA_SOURCE shows the text source of all stored objects in the database.

    Column
    Type
    Description

    LINE

    INTEGER

    The line number of the source.

    OID

    OID

    The ID of the object.


    DBA_VIEWS shows all views in the database.

    Column
    Type
    Description

    VIEW_NAME

    TEXT

    The name of the view

    OWNER

    NAME

    The name of the view generator


    DBA_IND_COLUMNS shows the columns of all indexes for all tables in the database..

    Column
    Type
    Description

    COLUMN_NAME

    TEXT

    The name of the column

    INDEX_NAME

    TEXT

    The name of the index

    VERSION_INFO

    TEXT

    The version information for each O2 extension and O2 and when it was updated.

    O2_EXTENSION_VERSION_INFO

    O2_MEMORY_CONTEXT_INFO

    O2_SHARED_MEMORY_INFO

    DUAL

    DBA_TAB_COLUMNS

    DBA_TABLES

    DBA_CONS_COLUMNS

    DBA_CONSTRAINTS

    PRODUCT_COMPONENT_VERSION

    DBA_OBJECTS

    DBA_PROCEDURES

    DBA_SOURCE

    DBA_VIEWS

    DBA_IND_COLUMNS

    Etcd

    This document describes how to use etcdctl, a command line tool installed with ETCD3, to check the status of ETCD3 cluster members and endpoint health, query the values of keys that meet certain conditions, and test the read/write performance of the cluster.

    Verify the installation of the command-line tool etcdctl

    etcdctl, a command-line tool for managing ETCD3 clusters, is provided with the etcd server binary. You can check if etcdctl is installed on a node and its version.

    $ which etcdctl
    /usr/local/bin/etcdctl
    
    $ etcdctl version
    etcdctl version: 3.5.6
    API version: 3.5

    There are two versions of etcdctl's API, v2 and v3, and you can specify which version of the API to call when running etcdctl by setting the environment variable ETCDCTL_API to 2 or 3, respectively.

    Starting with v3.4.0, the v3 version of the API is used by default, and this document also describes how to use the v3 version of the API.

    This section describes common options that can be specified when running the etcdctl command.

    • --endpoints : etcdctl Specify the endpoint URLs of the ETCD3 gRPC servers to access as a list separated by commas ,. If not specified, the localhost 127.0.0.1:2379 of the running environment is recognized as the default gRPC endpoint URL and communication is attempted. ◦ An invalid Endpoint URL returns an error as shown below.

    • -w, --write-out : Options for setting the format of output values include fields, json, protobuf, simple, and table .

    • --key


    Get a list and status of the cluster's members and endpoint URLs

    etcdctl member list in the etcdctl member list, the URL for advertised peer communication list and a list of URLs for client communication.

    • ID : A unique identifier for that node, used by the Raft algorithm to elect an ETCD leader node.

    • STATUS : A value indicating whether the node has booted and successfully participated in the cluster's leader election. started or unstarted. For ETCD3 nodes that have not yet been started, it has the value unstarted.

    • NAME

    You can check the access URL, database size, leader status, and Raft information of all member nodes in the cluster with etcdctl endpoint status .

    • ENDPOINT : A list of URLs for the advertised client communication of this node.

    • ID : Same as ENDPOINT

    • VERSION


    View data stored in an ETCD3 cluster.

    You can specify the --prefix option as an argument to the etcdctl get command to retrieve keys that match a specific preceding string.

    You can get a list of keys that fall betweentwo points in the key index space, precisely [key, range_end), by specifying a specific key value key and a different key range_end as arguments to the etcdctl get command.

    • All keys stored in ETCD3 are replaced by an array of bytes and stored in the Index space, and are indexed case-sensitively. aa < ab a\xff < b

    • Keys matching range_end are not included. (Exclusive)


    ETCD3 uses Multi-Version Concurrency Control (MVCC) based on revision information to control concurrent client access and maintain data consistency. If the cluster is maintained for a long period of time and there are many operations such as Patroni Switchover / Failover, there may be a problem that the DB size continues to increase even though the actual data size stored by Patroni in the ETCD3 cluster is small.

    The etcdctl compact command specifies a specific revision to define revisions from a point in time before that as no longer referenced. This behavior is a cluster-wide operation and can be executed without specifying a separate endpoint.

    The etcdctl defrag command deletes unreferenced revisions from the DB File to free up disk space. Without a separate --endpoints option, only the local node's disk space is freed. If you specify all endpoint URLs in the cluster with --endpoints option, it will free up disk space on each host.

    You can test the overall write throughput of your cluster for one minute with the etcdctl check perf command.

    --load option allows you to specify a different number of clients to request and a different number of requests per second.

    • s : 50 Clients

    • m : 200 Clients

    • l : 500 Clients

    The output will have a PASS / FAIL Criteria.

    • More than 90% of the requests generated will have Throughput.

    • All requests will be processed within 500 ms.

    • • The standard deviation (stddev) of the time it took to process the request is 100 ms or less.

    If the load imposed by the performance test is heavy, it is recommended to perform compact and defrag operations because the ETCD database size can increase significantly due to DB revision history.


    ETCD3 manages all of the cluster's configuration, including itself, such as the cluster nodes' connection URLs, cluster tokens, and listen URLs, like a database snapshot. If you change the configuration of a node in an already configured ETCD3 cluster and restart it with only the key-value data preserved, it will generally not work.

    If you want to change the environmental configuration of an already configured ETCD3 cluster to restart it, such as a failure caused by a service outage that requires a scale-in, a scale-out by adding new nodes, or a change in the IPv4 address of a host that requires the cluster to be reset, you should use the command line tool etcdctl to perform the recovery.

    For recovery, you need a snapshot of the ETCD3 node that contains the key-value data you want to import. A snapshot of ETCD3 corresponds to a data file in a relational database and stores not only the key- value data stored in the ETCD3 cluster at a specific point in time, but also the configuration information and raft state of the cluster. You can import a database file of ETCD3 stored in the file system or create it from a running ETCD3 cluster.

    The ETCD3 data path ETCD_DATA_DIR is located in the subpath member/snap/db.

    You can take a snapshot of the current point in time from the ETCD3 server using the snapshot save command in the command line tool etcdctl .

    • Only one ETCD3 server URL should be given as the ENDPOINT argument, even if a cluster of multiple nodes is running

    You can create ETCD3 cluster data from a snapshot using the snapshot restore command in the command line tool etcdctl.

    • As with the initial configuration of an ETCD3 cluster, all of the arguments included in the Database

      Snapshot during initial setup of a newly configured cluster must be given as command line arguments.

      • --name : Node name of the ETCD3 server to be repaired

    • • If the data is successfully recovered, a new cluster is created inside the directory named

      ${ETCD_NAME}.etcd.

    • • Restart the ETCD3 service based on the recovered data directory. The arguments used to recover the data must match the arguments used to restart the service. The created ${ETCD_NAME}.etcd directory should be located in the member/ subdirectory

    GitHub - etcd-io/etcd: Distributed reliable key-value store for the most critical data of a distributed systemGitHub

    PARENT

    TEXT

    The name of the parent memory context.

    LEVEL

    INTEGER

    The hierarchical level of the memory context.

    TOTAL_BYTES

    BIGINT

    The total amount of memory allocated by the context

    TOTAL_NBLOCKS

    BIGINT

    The number of blocks allocated.

    FREE_BYTES

    BIGINT

    The available space of the currently allocated memory.

    FREE_CHUNCKS

    BIGINT

    The number of available memory fragments.

    USED_BYTES

    BIGINT

    The amount of memory actually in use.

    DATA_TYPE

    TEXT

    The data type of the column.

    DATA_LENGTH

    INTEGER

    The length of the data (bit size of the number type).

    DATA_PRECISION

    INTEGER

    The precision of the NUMERIC type.

    DATA_SCALE

    INTEGER

    The number of decimal places.

    NULLABLE

    TEXT

    Whether NULLs are allowed in the column.

    COLUMN_ID

    INTEGER

    The consecutive numbers in the column.

    TABLE_NAME

    TEXT

    The name of table

    CONSTRAINT_TYPE

    TEXT

    Constraint type 'P' is Primary key and 'R' is Referential integrity.

    TABLE_NAME

    TEXT

    The name of table

    R_CONSTRAINT_NAME

    TEXT

    Unique for the referenced table

    STATUS

    TEXT

    Architecture and build mode

    OBJECT_ID

    OID

    오브젝트 ID다.

    OBJECT_TYPE

    TEXT

    오브젝트 타입이다.

    CREATED

    TIMESTAMP

    오브젝트 생성일시다. 호환성을 위해 추가된 컬럼이다.(Default : NULL)

    LAST_DDL_TIME

    TIMESTAMP

    DDL로 인한 오브젝으 및 하위 오브젝트의 변경에 대한 시점이다. 호환성을 위해 추가된 컬럼이다.(Default : NULL)

    STATUS

    TEXT

    오브젝트의 상태이다.

    NAMESPACE

    OID

    오브젝트의 NAMESPACE다.

    TEXT

    TEXT

    The text source of the saved object.

    NAME

    TEXT

    The name of the object.

    TYPE

    TEXT

    The type of the object.

    TABLE_NAME

    TEXT

    The name of the table

    : Specifies the path to the Client Key file to use for TLS.
  • --cert : Specifies the path to the Client certificate file to use for TLS authentication.

  • --cacert : : Specifies the path to the certificate authority (CA) certificate file to use for TLS.

  • : The unique name of the node, specified by the --name argument when starting the ETCD3
  • PEER ADDRS : A list of URLs for this node's advertised peer communications.

  • CLIENT ADDRS : A list of URLs for this node's advertised client communications.

  • IS LEARNER : The member has learned the snapshot and WAL replication status from the ETCD cluster. Indicates if it is a Learner node that supports but does not participate in the leader election quorum.

  • : Indicates the version of the ETCD3 server running on this node.
  • DB SIZE : Indicates the size of the ETCD3 database stored on disk.

  • IS LEADER : Indicates whether the node is the Raft Leader for this cluster.

  • IS LEARNER : Same as IS LEADER

  • RAFT TERM : Current term of office (Term) according to the Raft algorithm. The value is incremented by 1 each time a new Leader is elected.

  • RAFT INDEX : Indicates the log entry location of the write operations stored on this node. The node with the highest Raft Index (i.e., the most up-to-date), which is referenced when electing a leader, has priority when electing a leader.

  • RAFT APPLIED INDEX : Indicates the location of the log entry that is applied to the local environment key-value store of the node and is readable (Applied). Depending on the CPU and disk environment of the node, the Raft Applied Index may have a value less than the Raft Index (i.e., a data write operation) may occur, in which case Data Consistency may not be maintained depending on client settings. The behavior depends on the value of the etcdctl get flag --consistency. -- consistency=s (Serializable, default) fetches data from a point in time in the past.

  • ERRORS : : Represents the problem detected on the endpoint of this node in the form of a message.

  • xl : 1000 Clients

    --initial-cluster
    : Node name of all ETCD3 servers in the cluster and endpoint URL for

    peer communication

  • --initial-cluster-token : Initialize Token to join the cluster

  • --initial-advertise-peer-urls : This node's Endpoint URL for peer communication

  • --skip-hash-check option is used to skip verifying the data integrity of the original snapshot being recovered.

    • For snapshots created by a running ETCD3 server with the snapshot save command, data integrity is preserved and can be restored normally without this option.

    • ETCD3 data db files copied from the filesystem contain cluster meta-information at runtime and cannot be recovered normally without this option. Skip data integrity verification by giving the --skip- hash-check option.

  • Common options

    Example

    Note

    https://github.com/etcd-io/etcd/issues/9600

    View Cluster status

    View cluster members

    View Cluster endpoint

    View Data 데이터 조회

    View with Prefix

    View with Range

    Database maintenance

    Specify which revisions to clean up

    Disk defragmentation

    Write performance test

    Recovery

    Veryfy snapshot

    Check in the filesystem

    Generate from a running ETCD3

    Recovering data from snapshots

    Note

    https://github.com/etcd-io/etcd/blob/v3.4.19/Documentation/op-guide/recovery.md

    $ etcdctl member list
    Error:  dial tcp 127.0.0.1:2379: connect: connection refused
    $ ETCDCTL_API=3 etcdctl --endpoints="https://192.168.0.10:2379,https://192.168.0.11:2379" \
      --key="./etcd-client-key.pem" \
      --cert="./etcd-client-crt.pem" \
      --cacert="./etcd-ca-crt.pem" \
      member list
    $ etcdctl member list
    670b863301943618, started, node1, http://192.168.0.10:2380, http://192.168.0.10:2379, false
    7825d7b04510b842, started, node3, http://192.168.0.11:2380, http://192.168.0.11:2379, false
    c8245114d55ec576, started, node2, http://192.168.0.12:2380, http://192.168.0.12:2379, false
    
    $ etcdctl member list -w table
    +------------------+---------+-------+--------------------------+--------------------------+------------+
    |        ID        | STATUS  | NAME  |        PEER ADDRS        |       CLIENT ADDRS       | IS LEARNER |
    +------------------+---------+-------+----------------------------+------------------------+------------+
    | 670b863301943618 | started | node1 | http://192.168.0.10:2380 | http://192.168.0.10:2379 |      false |
    | 7825d7b04510b842 | started | node3 | http://192.168.0.11:2380 | http://192.168.0.11:2379 |      false |
    | c8245114d55ec576 | started | node2 | http://192.168.0.12:2380 | http://192.168.0.12:2379 |      false |
    +------------------+---------+-------+----------------------------+------------------------+------------+
    $ etcdctl endpoint status -w table
    +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
    |         ENDPOINT         |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
    +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
    | http://192.168.0.10:2379 | 670b863301943618 |  3.5.21 |  168 kB |      true |      false |         6 |        520 |                520 |        |
    | http://192.168.0.11:2379 | c8245114d55ec576 |  3.5.21 |  168 kB |     false |      false |         6 |        520 |                520 |        |
    | http://192.168.0.12:2379 | 7825d7b04510b842 |  3.5.21 |  168 kB |     false |      false |         6 |        520 |                520 |        |
    +--------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
    $ etcdctl get --prefix "/opensql/opensql/members" -w simple
    /opensql/opensql/members/pg-1
    {"conn_url":"postgres://192.168.131.12:5432/postgres","api_url":"http://192.168.131.12:8008/patroni","state":"running","role":"replica","version":"4.0.5","proxy_url":"postgres://192.168.131.15:6432/postgres","xlog_location":223510016,"replication_state":"streaming","timeline":3}
    /opensql/opensql/members/pg-2
    {"conn_url":"postgres://192.168.131.13:5432/postgres","api_url":"http://192.168.131.13:8008/patroni","state":"running","role":"primary","version":"4.0.5","proxy_url":"postgres://192.168.131.15:6432/postgres","xlog_location":223510016,"timeline":3}
    /opensql/opensql/members/pg-3
    {"conn_url":"postgres://192.168.131.14:5432/postgres","api_url":"http://192.168.131.14:8008/patroni","state":"running","role":"replica","version":"4.0.5","proxy_url":"postgres://192.168.131.15:6432/postgres","xlog_location":223510016,"replication_state":"streaming","timeline":3}
    $ etcdctl get "/opensql/opensql/members/pg-1" "/opensql/opensql/members/pg-3"
    /opensql/opensql/members/pg-1
    {"conn_url":"postgres://192.168.131.12:5432/postgres","api_url":"http://192.168.131.12:8008/patroni","state":"running","role":"replica","version":"4.0.5","proxy_url":"postgres://192.168.131.15:6432/postgres","xlog_location":223510016,"replication_state":"streaming","timeline":3}
    /opensql/opensql/members/pg-2
    {"conn_url":"postgres://192.168.131.13:5432/postgres","api_url":"http://192.168.131.13:8008/patroni","state":"running","role":"primary","version":"4.0.5","proxy_url":"postgres://192.168.131.15:6432/postgres","xlog_location":223510016,"timeline":3}
    
    $ etcdctl get "/opensql/opensql/failover" "/opensql/opensql/historz"
    /opensql/opensql/failover
    {}
    /opensql/opensql/history
    [[1,223438192,"no recovery target specified","2025-04-18T14:27:03.269756+09:00","pg-1"],[2,223438824,"no recovery target specified","2025-04-21T15:13:37.632010+09:00","pg-2"]]
    ## Check Endpoint Status to get the most recent revision information maintained by each node.
    $ etcdctl endpoint status -w json | jq | grep 'revision'
            "revision": 447871,
            "revision": 447871,
            "revision": 447871,
    
    ## Marks revisions prior to this revision as no longer referenced.
    $ rev=447871
    $ etcdctl compact $rev
    compacted revision 447871
    $ etcdctl defrag --endpoints "http://192.168.0.10:2379,http://192.168.0.11:2379,http://192.168.0.12:2379"
    Finished defragmenting etcd member[http://192.168.0.10:2379]
    Finished defragmenting etcd member[http://192.168.0.11:2379]
    Finished defragmenting etcd member[http://192.168.0.12:2379]
    
    $ etcdctl endpoint status --endpoints "..."
    http://192.168.0.10:2379, 670b863301943618, 3.5.21, 25 kB, true, false, 8, 448000, 448000, 
    http://192.168.0.11:2379, c8245114d55ec576, 3.5.21, 25 kB, false, false, 8, 448000, 448000, 
    http://192.168.0.12:2379, 7825d7b04510b842, 3.5.21, 25 kB, false, false, 8, 448000, 448000,
    $ etcdctl check perf
     60 / 60 Booooooooooooooooooooooooooooooooooooooooooooooooooooooom! 100.00% 1m0s
    PASS: Throughput is 150 writes/s
    PASS: Slowest request took 0.291186s
    PASS: Stddev is 0.029467s
    PASS
    $ etcdctl check perf
     60 / 60 Booooooooooooooooooooooooooooooooooooooooooooooooooooooom! 100.00% 1m0s
    PASS: Throughput is 150 writes/s
    Slowest request took too long: 0.535645s
    PASS: Stddev is 0.079037s
    FAIL
    
    $ etcdctl check perf --load="xl"
     60 / 60 Booooooooooooooooooooooooooooooooooooooooooooooooooooooom! 100.00% 1m0s
    FAIL: Throughput too low: 3668 writes/s
    Slowest request took too long: 0.645609s
    Stddev too high: 0.105516s
    FAIL
    $ ls -l $ETCD_DATA_DIR/member/snap/
    total 168
    -rw-------. 1 opensql opensql 16805888 Apr 18 14:29 db
    
    $ cp $ETCD_DATA_DIR/member/snap/db ./mysnapshot.db
    $ ETCDCTL_API=3 etcdctl --endpoints=${ENDPOINT} snapshot save mysnapshot.db
    
    {"level":"info","ts":"2025-04-21T12:18:30.406283+0900","caller":"snapshot/v3_snapshot.go:65","msg":"created temporary db file","path":"mysnapshot.db.part"}
    {"level":"info","ts":"2025-04-21T12:18:30.407142+0900","logger":"client","caller":"v3@v3.5.21/maintenance.go:212","msg":"opened snapshot stream; downloading"}
    {"level":"info","ts":"2025-04-21T12:18:30.407162+0900","caller":"snapshot/v3_snapshot.go:73","msg":"fetching snapshot","endpoint":"192.168.131.12:2379"}
    {"level":"info","ts":"2025-04-21T12:18:30.432538+0900","logger":"client","caller":"v3@v3.5.21/maintenance.go:220","msg":"completed snapshot read; closing"}
    {"level":"info","ts":"2025-04-21T12:18:30.480983+0900","caller":"snapshot/v3_snapshot.go:88","msg":"fetched snapshot","endpoint":"192.168.131.12:2379","size":"168 kB","took":"now"}
    {"level":"info","ts":"2025-04-21T12:18:30.481039+0900","caller":"snapshot/v3_snapshot.go:97","msg":"saved","path":"mysnapshot.db"}
    Snapshot saved at mysnapshot.db
    $ ETCDCTL_API=3 etcdctl snapshot restore ./mysnapshot.db \
      --name node3 \
      --initial-cluster node1=http://192.168.0.8:2380,node2=http://192.168.0.9:2380,node3=http://192.168.0.10:2380 \
      --initial-cluster-token new-etcd-cluster \
      --initial-advertise-peer-urls http://192.168.0.10:2380 \
      --skip-hash-check \
      # ...
    
    Deprecated: Use `etcdutl snapshot restore` instead.
    
    snapshot/v3_snapshot.go:248	restoring snapshot	{"path": "member/snap/db", "wal-dir": "node3.etcd/member/wal", "data-dir": "node3.etcd", "snap-dir": "node3.etcd/member/snap", "stack": "go.etcd.io/..." }
    membership/store.go:141	Trimming membership information from the backend...
    membership/cluster.go:421	added member	{"cluster-id": "154dfe96307df6f0", "local-member-id": "0", "added-peer-id": "3dfe6fc7fff49d22", "added-peer-peer-urls": ["http://192.168.0.8:2380"]}
    membership/cluster.go:421	added member	{"cluster-id": "154dfe96307df6f0", "local-member-id": "0", "added-peer-id": "7f846315e3b9872d", "added-peer-peer-urls": ["http://192.168.0.9:2380"]}
    membership/cluster.go:421	added member	{"cluster-id": "154dfe96307df6f0", "local-member-id": "0", "added-peer-id": "c0ea9022befd3eaa", "added-peer-peer-urls": ["http://192.168.0.10:2380"]}
    snapshot/v3_snapshot.go:269	restored snapshot	{"path": "member/snap/db", "wal-dir": "node3.etcd/member/wal", "data-dir": "node3.etcd", "snap-dir": "node3.etcd/member/snap"}
    $ ls -l
    total 0
    drwx------. 3 root root  20 Mar 17 14:48 node1.etcd
    
    $ ls -l node1.etcd/
    drwx------. 2 root root 246 Mar 17 14:41 snap
    drwx------. 2 root root 257 Mar 17 14:41 wal
    $ rm -rf $ETCD_DATA_DIR/member
    
    $ cp -r node1.etcd $ETCD_DATA_DIR/member
    
    ## Check the contents of the etcd.env file referenced in the Service definition
    $ vi /etc/etcd/etcd.env
    ETCD_NAME=node1
    
    ETCD_INITIAL_CLUSTER=node1=http://192.168.0.8:2380,node2=http://192.168.0.9:2380,node3=http://192.168.0.10:2380
    ETCD_INITIAL_CLUSTER_TOKEN=new-etcd-cluster
    ETCD_INITIAL_CLUSTER_STATE=new
      --initial-cluster-token new-etcd-cluster \
      --initial-advertise-peer-urls http://192.168.0.8:2380 \
    
    $ systemctl restart etcd.service
    Logo

    Patroni

    patronictl is a Python 3-based CLI (command line interface) installed with the Patroni package, which provides functions for monitoring clusters and accessing DCS using the REST API provided by Patroni clusters.

    Used to manage PostgreSQL clusters, check their status, and verify configuration settings.

    Check Installation

    patronictl is provided by default with the Python 3 package patroni. You can check whether patronictl is installed on the node and its version as follows.

    $ which patronictl 
    /usr/local/bin/patronictl
    
    $ patronictl version
    patronictl version 3.3.0


    Configure Local Configuration File

    This is a configuration value that is read from a yml file located in the path that is input as a parameter when the Patroni process runs.

    You can send a SIGHUP signal to the Patroni process or send a POST /reload request to the REST API server to reload the configuration file. The path to the default template environment configuration file is /etc/patroni/patroni.yml. Create a yml file in that path and modify the contents of the file to suit the environment you want to configure

    • You can define meta information for the Patroni cluster, etcd connection information, logging configuration, REST API server configuration, and PostgreSQL parameter information.

    • The PostgreSQL parameter set is defined in the Local Configuration and Global Dynamic. If there are duplicate keys, the value in the Local Configuration takes precedence.

    • Configuration below. Define the bootstrap.dcs item to set the initial configuration set for Global Dynamic Configuration below.

    • scope: the Patroni cluster you want to configure. PostgreSQL parameters Applied to cluster_name.

    • namespace: Prefix of the key to use within the Configuration Store.

    • name: The name of this instance (node). Must be unique within the cluster; if not set, the hostname is used.

    • log.type: Specifies the log format. Two options are supported: plain and json. Using the json

      type requires an additional installation of the Python package patroni[jsonlogger].

    • log.format: Specify the format of the log messages. Use the LogRecord module of the Python

    • restapi.listen: The IPv4 address and port number to which the Patroni REST API server will be bound.

    • restapi.connect_address: The externally identifiable Rest API server address of this node to use for communication between Patroni members. This value is also parsed and used as the Host address when making API calls to lookup cluster members.

    Example for etcd v3

    • etcd3.protocol: Supports http or https as the protocol to use when accessing the etcd3 cluster. http is used as the default value, and if it is https, you need to set etcd3.cacert , etcd3.cert , etcd3.key additionally.

    • etcd3.host: etcd3 endpoint URL

    If a PostgreSQL database is not initialized on the node when Patroni starts, use the information in this section to initialize a database instance. If there is an already configured PostgreSQL database on the node, the contents of this section or any changes you add will not be reflected in Patroni.

    The contents of the sub-item bootstrap.dcs initialize the Patroni cluster and are the values that will be stored in the DCS as Global Dynamic Configuration.

    • bootstrap.dcs: When When initializing with Patroni cluster preferences, this is the Global Dynamic Configuration set stored in /<namespace>/<scope>/config in DCS.

    • bootstrap.initdb: If you set initdb (default) as the database initialization method, this is an array of parameters to pass to initdb when it is run.

    Defines system parameters, default users, host-based authentication rules, database parameters, and other settings for the PostgreSQL database.

    The key in the Global Dynamic Configuration is the same as the one specified by postgresql. If the same key is defined twice in this file and in the Global Dynamic Configuration, the value defined in this file (i.e., the Local Configuration File) takes precedence.

    • postgresql.listen: Enter the address for the PostgreSQL server to be run by Patroni on this node to listen to in the form of <IP address>:<Port number> .

    • postgresql.connect_address: Enter the connection URL of PostgreSQL to be referenced by other nodes or client applications. This is the value returned when retrieving cluster information and DSN.

    • postgresql.proxy_address: If you have a proxy server to access the PostgreSQL server, you can enter the URL of that proxy server for service discovery as needed, and this value is stored with the cluster information in DCS.


    patronictl does not store any configuration settings and must be given a DCS connection URL or Patroni connection URL to get information about the cluster on each run.

    Use the Configuration .yml file that you used to configure the cluster as an argument as shown below.

    You can also register with a Linux alias as shown below.

    Displays the configuration nodes in the cluster, as well as the connection and status information for each node.

    Outputs the DSN (Data Source Name) of the cluster node. If no separate option is specified, outputs the connection information for the leader node.

    You can also print access information for members with specific roles, or you can print access information for specific members by name.

    Restart the PostgreSQL process on one of the member nodes of the cluster. The cluster name (set in the meta information) must be given as an argument, with the name of the member node as an optional extra. If no member name is specified, all nodes are restarted once.

    Provides an interactive prompt to enter a restart date and time (with the option to restart immediately and the ability to schedule a restart by specifying a timestamp), and the ability to filter by checking the version of the PostgreSQL server to restart.

    This function reloads the configuration without restarting the PostgreSQL server on one of the member nodes of the cluster. The cluster name must be given as an argument, with the name of the member node as an option.

    Confirm whether you want to schedule a cluster member reload through an interactive prompt.

    PostgreSQL variables (GUC) with Context values of internal and postmaster cannot be changed by the Reloading feature. The internal variable is determined when compiling the server program or when initializing the database with the initdb command and cannot be changed without reinstalling the database, and the postmaster variable can only be changed by restarting the PostgreSQL process.

    View the history of Failover and Switchover that occurred in the cluster.

    You can run a database query against a PostgreSQL node with a specific role to see the results.

    If there is no Leader node due to a failure in the cluster, you can manually run a failover.

    You can also perform a manual failover with the patronictl failover command in a healthy cluster. However, if you want to change the Leader instance in a healthy cluster, we recommend using the patronictl switchover command.

    This action converts the PostgreSQL/Patroni Leader node to a Replica and promotes one of the other Replica nodes to Leader.

    Stops the automatic failover feature of the Patroni cluster and puts the cluster into Maintenance Mode.

    Exit maintenance mode with the Resume command and re-enable the automatic failover feature of the cluster.

    You can view the DCS to see the configuration currently applied to your Patroni cluster.

    You can modify the Dynamic Configuration values of your Patroni cluster stored in DCS.

    You can run a text editor or vi specified by the local user's EDITOR environment variable as a subprocess to modify and save the configuration in TTY format.

    logging package. ◦If the log type is plain, it should be given as a string like the example above. ◦If the log type is json, it can be given as an array of items to be logged. ◦See https://docs.py ◦log.dir: The path to the directory where Patroni logs will be written, and the default retention for log files. The size is 425 MB. ◦For items not mentioned, see the documentation at the links below;

    etcd3.hosts: Array of etcd3 cluster endpoint URLs

    postgresql.data_dir: The data path to the PostgreSQL server. The user running the Patroni process must have access to this path. If this path is empty, the Patroni process will run with the initdb behavior.

  • postgresql.bin_dir: Specifies the path where the PostgreSQL executable binaries pg_ctl, initdb, postgres, etc. are located.

  • postgresql.config_dir: Path to the directory to hold the PostgreSQL configuration file

    postgresql.conf. The default value is the same as the data_dir value.

  • postgresql.pg_hba: Enter items to write to the pg_hba.conf file (PostgreSQL's default host-based authentication settings) that Patroni will create. This entry is ignored if the PostgreSQL parameter hba_file is set to a custom value.

  • postgresql.parameters: PostgreSQL database parameters. They are entered in key-value format a n d are used when generating the postgresql.conf file.

  • scope: batman
    #namespace: /service/
    name: postgresql0
    log:
      type: plain
      format: "[%(asctime)s] [%(module)s] [%(levelname)s]: %(message)s"
      dir: /etc/patroni/logs
    restapi:
      listen: 0.0.0.0:8008
      connect_address: 192.168.0.100:8008
    etcd3:
      protocol: http
      # host: 192.168.0.100:2379
      hosts:
      - 192.168.0.1:2379
      - 192.168.0.2:2379
      - 192.168.0.3:2379
    bootstrap:
      # This section will be written into Etcd:/<namespace>/<scope>/config after initializing new cluster
      # and all other cluster members will use it as a `global configuration`.
      # WARNING! If you want to change any of the parameters that were set up
      # via `bootstrap.dcs` section, please use `patronictl edit-config`!
      dcs:
        ttl: 30
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 1048576
    #    primary_start_timeout: 300
    #    synchronous_mode: false
        #standby_cluster:
          #host: 127.0.0.1
          #port: 1111
          #primary_slot_name: patroni
        slots:
          barman:
            type: physical
        postgresql:
          use_pg_rewind: true
          use_slots: true
          parameters:
    #        wal_level: hot_standby
    #        hot_standby: "on"
            max_connections: 100
            max_worker_processes: 8
    #        wal_keep_segments: 8
    #        max_wal_senders: 10
    #        max_replication_slots: 10
    #        max_prepared_transactions: 0
    #        max_locks_per_transaction: 64
    #        wal_log_hints: "on"
    #        track_commit_timestamp: "off"
    #        archive_mode: "on"
    #        archive_timeout: 1800s
    #        archive_command: mkdir -p ../wal_archive && test ! -f ../wal_archive/%f && cp %p ../wal_archive/%f
    #      recovery_conf:
    #        restore_command: cp ../wal_archive/%f %p
    
      # some desired options for 'initdb'
      initdb:  # Note: It needs to be a list (some options need values, others are switches)
      - encoding: UTF8
      - data-checksums
    postgresql:
      listen: 0.0.0.0:5432
      connect_address: 192.168.0.100:5432
      proxy_address: 127.0.0.1:6432  # The address of connection pool (e.g., pgbouncer) running next to Patroni/Postgres. Only for service discovery.
      #data_dir: data/postgresql0
      data_dir: /var/lib/pgsql/16/data
      bin_dir: /usr/pgsql-16/bin
    #  config_dir:
      pgpass: /tmp/pgpass0
      authentication:
        replication:
          username: patroni_repl
          password: patroni_repl
        superuser:
          username: postgres
          password: zalando
        rewind:  # Has no effect on postgres 10 and lower
          username: patroni_rewind
          password: patroni_rewind
      pg_hba:
      # For kerberos gss based connectivity (discard @.*$)
      - local all all trust
      - host replication patroni_repl 192.168.0.0/24 trust
      - host replication patroni_repl 127.0.0.1/32 trust
      - host all all 0.0.0.0/0 md5
      - host all barman 192.168.0.0/24 trust
      - host replication streaming_barman 192.168.0.0/24 trust
      parameters:
        log_line_prefix: '%m [%r] [%u] [%a]'
        archive_command: 'barman-wal-archive node4 pg %p'
        archive_mode: 'true'
        wal_level: 'replica'
    $ patronictl list
    2024-10-29 17:20:56,603 - WARNING - Listing members: No cluster names were provided 
    
    $ patronictl list opensql
    Error: Can not find suitable configuration of distributed configuration store
    Available implementations: etcd, etcd3, kubernetes
    $ patronictl -c /etc/patroni/patroni.yml list
    
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+ 
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   | 
    +-------------+-------------+---------+-----------+----+-----------+------------------------+ 
    | postgresql0 | 192.1.1.218 | Replica | streaming | 16 |         0 |                        | 
    +-------------+-------------+---------+-----------+----+-----------+------------------------+ 
    | postgresql1 | 192.1.1.236 | Replica | streaming | 16 |         0 | failover_priority: 150 | 
    |             |             |         |           |    |           | nofailover: false      | 
    +-------------+-------------+---------+-----------+----+-----------+------------------------+ 
    | postgresql2 | 192.1.1.238 | Leader  | running   | 16 |           |                        | 
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    $ alias pctl='patronictl -c /etc/patroni/patroni.yml'
    
    $ echo 'alias pctl="patronictl -c /etc/patroni/patroni.yml"' >> ~/.bashrc
    
    $ pctl list
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | streaming | 16 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | streaming | 16 |         0 | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Leader  | running   | 16 |           |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    $ patronictl list
    2024-10-29 15:36:15,282 - WARNING - Listing members: No cluster names were provided
    
    ## View as a table(default)
    $ patronictl -c /etc/patroni/patroni.yml list
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | streaming | 16 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | streaming | 16 |         0 | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Leader  | running   | 16 |           |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    
    ## View as a JSON 
    $ patronictl -c /etc/patroni/patroni.yml list -f json
    [{"Cluster": "opensql", "Member": "postgresql0", "Host": "192.1.1.218", "Role": "Leader", "State": "running", "TL": 17}, {"Cluster": "opensql", "Member": "postgresql1", "Host": "192.1.1.236", "Role": "Replica", "State": "streaming", "TL": 17, "Lag in MB": 0, "Tags": {"nofailover": false, "failover_priority": 150}}, {"Cluster": "opensql", "Member": "postgresql2", "Host": "192.1.1.238", "Role": "Replica", "State": "streaming", "TL": 17, "Lag in MB": 0}]
    $ patronictl -c /etc/patroni/patroni.yml topology
    + Cluster: opensql (7364637789542980847) +-----------+----+-----------+---------------------------------------------+
    | Member        | Host        | Role    | State     | TL | Lag in MB | Tags                                        |
    +---------------+-------------+---------+-----------+----+-----------+---------------------------------------------+
    | postgresql2   | 192.1.1.238 | Leader  | running   | 21 |           |                                             |
    | + postgresql0 | 192.1.1.218 | Replica | streaming | 21 |         0 |                                             |
    | + postgresql1 | 192.1.1.236 | Replica | streaming | 21 |         0 | {failover_priority: 150, nofailover: false} |
    +---------------+-------------+---------+-----------+----+-----------+---------------------------------------------+
    $ patronictl -c /etc/patroni/patroni.yml dsn
    host=192.1.1.238 port=5432
    $ patronictl -c /etc/patroni/patroni.yml dsn -r replica
    host=192.1.1.218 port=5432
    
    $ patronictl -c /etc/patroni/patroni.yml dsn -m postgresql1
    host=192.1.1.236 port=5432
    $ pctl restart <cluster_name>
    $ pctl restart opensql postgresql0
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | streaming | 16 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | streaming | 16 |         0 | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Leader  | running   | 16 |           |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    When should the restart take place (e.g. 2024-10-31T12:16)  [now]:
    ## restart immediately arter typing now
    
    Are you sure you want to restart members postgresql0? [y/N]:
    
    Restart if the PostgreSQL version is less than provided (e.g. 9.5.2)  []:
    
    Success: restart on member postgresql0
    $ pctl reload <cluster_name>
    $ pctl reload opensql
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | streaming | 16 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | streaming | 16 |         0 | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Leader  | running   | 16 |           |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    Are you sure you want to reload members postgresql0, postgresql1, postgresql2? [y/N]:
    Reload request received for member postgresql0 and will be processed within 10 seconds
    Reload request received for member postgresql1 and will be processed within 10 seconds
    Reload request received for member postgresql2 and will be processed within 10 seconds
    $ pctl history
    +----+------------+------------------------------+----------------------------------+-------------+
    | TL |        LSN | Reason                       | Timestamp                        | New Leader  |
    +----+------------+------------------------------+----------------------------------+-------------+
    |  1 |   26875256 | no recovery target specified | 2024-05-03T14:20:28.841738+09:00 | postgresql2 |
    |  2 |  213072680 | no recovery target specified | 2024-05-03T14:45:37.945208+09:00 | postgresql1 |
    |  3 |  213101064 | no recovery target specified | 2024-05-03T14:46:14.686504+09:00 | postgresql2 |
    |  4 |  805306528 | no recovery target specified | 2024-05-28T17:44:02.808722+09:00 | postgresql1 |
    |  5 |  855638176 | no recovery target specified | 2024-05-28T17:54:12.358175+09:00 | postgresql2 |
    |  6 | 1879048352 | no recovery target specified | 2024-07-30T15:58:10.527327+09:00 | postgresql0 |
    |  7 | 1895825568 | no recovery target specified | 2024-07-30T15:58:52.408275+09:00 | postgresql2 |
    |  8 | 2013266080 | no recovery target specified | 2024-08-12T10:00:38.641449+09:00 | postgresql2 |
    |  9 | 2030043296 | no recovery target specified | 2024-08-12T10:04:16.370771+09:00 | postgresql2 |
    | 10 | 2046820512 | no recovery target specified | 2024-08-12T10:05:07.178679+09:00 | postgresql2 |
    | 11 | 2063597728 | no recovery target specified | 2024-08-12T10:47:06.368795+09:00 | postgresql2 |
    | 12 | 2080374944 | no recovery target specified | 2024-08-12T10:50:59.596850+09:00 | postgresql2 |
    | 13 | 2332033184 | no recovery target specified | 2024-10-28T13:41:28.936064+09:00 | postgresql1 |
    | 14 | 2348810400 | no recovery target specified | 2024-10-28T16:04:27.587725+09:00 | postgresql0 |
    | 15 | 2365587616 | no recovery target specified | 2024-10-28T16:16:32.842442+09:00 | postgresql2 |
    +----+------------+------------------------------+----------------------------------+-------------+
    $ patronictl -c /etc/patroni/patroni.yml query -U postgres --password -c "SELECT VERSION();"
    Password: 
    version
    PostgreSQL 14.13 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
    $ patronictl -c /etc/patroni/patroni.yml failover
    
    Current cluster topology
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | streaming | 20 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Leader  | running   | 20 |           | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Replica | streaming | 20 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    Candidate ['postgresql0', 'postgresql2'] []: postgresql2
    Are you sure you want to failover cluster opensql, demoting current leader postgresql1? [y/N]: y
    2024-11-04 16:36:12.20700 Successfully failed over to "postgresql2"
    + Cluster: opensql (7364637789542980847) --------+----+-----------+------------------------+
    | Member      | Host        | Role    | State   | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | running | 20 |         0 |                        |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | stopped |    |   unknown | failover_priority: 150 |
    |             |             |         |         |    |           | nofailover: false      |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Leader  | running | 20 |           |                        |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    $ patronictl -c /etc/patroni/patroni.yml switchover
    
    Current cluster topology
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Leader  | running   | 19 |           |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | streaming | 19 |         0 | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Replica | streaming | 19 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    Primary [postgresql0]: postgresql0
    Candidate ['postgresql1', 'postgresql2'] []: postgresql1
    When should the switchover take place (e.g. 2024-11-04T17:34 )  [now]: now
    Are you sure you want to switchover cluster opensql, demoting current leader postgresql0? [y/N]: y
    2024-11-04 16:35:07.34291 Successfully switched over to "postgresql1"
    + Cluster: opensql (7364637789542980847) --------+----+-----------+------------------------+
    | Member      | Host        | Role    | State   | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | stopped |    |   unknown |                        |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Leader  | running | 19 |           | failover_priority: 150 |
    |             |             |         |         |    |           | nofailover: false      |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Replica | running | 19 |         0 |                        |
    +-------------+-------------+---------+---------+----+-----------+------------------------+
    $ patronictl -c /etc/patroni/patroni.yml pause
    Success: cluster management is paused
    
    $ patronictl -c /etc/patroni/patroni.yml list
    + Cluster: opensql (7364637789542980847) ----------+----+-----------+------------------------+
    | Member      | Host        | Role    | State     | TL | Lag in MB | Tags                   |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql0 | 192.1.1.218 | Replica | streaming | 25 |         0 |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql1 | 192.1.1.236 | Replica | streaming | 25 |         0 | failover_priority: 150 |
    |             |             |         |           |    |           | nofailover: false      |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
    | postgresql2 | 192.1.1.238 | Leader  | running   | 25 |           |                        |
    +-------------+-------------+---------+-----------+----+-----------+------------------------+
     Maintenance mode: on
    $ patronictl -c /etc/patroni/patroni.yml resume
    Success: cluster management is resumed
    $ patronictl -c /etc/patroni/patroni.yml show-config
    loop_wait: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      parameters:
        archive_command: barman-wal-archive node4 pg %p
        archive_mode: 'true'
        authentication_timeout: '200'
        log_line_prefix: '%m [%r] [%u] [%a]'
        max_connections: '250'
        wal_level: replica
        wal_receiver_timeout: '30000'
      pg_hba:
      - local all all trust
      - host replication patroni_repl 192.1.1.218/26 trust
      - host replication patroni_repl 127.0.0.1/32 trust
      - host all all 0.0.0.0/0 md5
      - host all barman 192.1.1.218/26 trust
      - host replication streaming_barman 192.1.1.218/26 trust
      use_pg_rewind: true
      use_slots: true
    retry_timeout: 10
    slots:
      barman:
        type: physical
    ttl: 30
    $ pctl edit-config
    loop_wait: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      parameters:
        archive_command: barman-wal-archive node4 pg %p
        archive_mode: 'false'
        authentication_timeout: '500'
        log_line_prefix: '%m [%r] [%u] [%a]'
        max_connections: 500
        wal_level: replica
        wal_receiver_timeout: '30000'
      pg_hba:
      - local all all trust
      - host replication patroni_repl 192.1.1.218/26 trust
      - host replication patroni_repl 127.0.0.1/32 trust
      - host all all 0.0.0.0/0 md5
      - host all barman 192.1.1.218/26 trust
      - host replication streaming_barman 192.1.1.218/26 trust
      use_pg_rewind: true
      use_slots: true
    retry_timeout: 10
    slots:
      barman:
        type: physical
    ttl: 45
    ~
    ~
    ~
    ~
    "/tmp/opensql-config-m332oce3.yaml" 25L, 683C

    Cluster meta information

    Logging

    Rest API

    DCS (etcd)

    Bootstrapping

    PostgreSQL

    Usage

    Check Cluster Information

    Topology Output

    DSN Output

    Restart

    Reloading

    View History

    Query

    Failover

    Switchover

    Pause / Resume

    Check Configuration

    Modify Configuration

    thon.org /3.6/library /logg ing .html#logrecord-attributes
    https://patroni.readthedocs.io/en/latest/ENVIRONMENT.html#log

    OpenProxy

    Overview

    This section explains how to set up and run OpenProxy, which handles OpenSQL’s connection pooling, load balancing, and virtual IP failover functions.

    Environment configuration

    This document lists the values that can be set when OpenProxy is run. If you want to run OpenProxy with a configuration file of your choice, enter the path to the configuration file after the OpenProxy command.

    General Settings

    These are the values declared in [general]. The values set in [general] set network settings, such as port, and the admin name and password for OpenProxy.

    Variable name
    Type
    Default
    Description

    Set this under the [general.virtual_router] section if you want to enable OpenProxy's virtual IP-related features. If not, remove the section.

    Variable name
    Type
    Default
    Description

    [pools.{pool_name}]

    If you want to add a new connection, add it to [pools].

    Variable name
    Type
    Default
    Description

    Openproxy's Connection pool can be used by registering multiple users.

    User configuration allows for user-specific settings and further overrides of general and pool settings.

    Register user-related entries in the [pools.{pool_name}.users.0] sub-entry.

    Variable name
    Type
    Default
    Description

    You need to define the database server address to connect to the pools.{pool_name}.shards.0 sub-section.

    Variable name
    Type
    Default
    Description

    The example setup above makes the following assumptions.

    • The “my_database” pooler you set up runs on the same machine as PostgreSQL.

    • postgres database is defined.

    • User: developer, password: very-security-password has CONNECT privileges in the postgres database.


    Execute the installed openproxy binary as shown below. You can specify the path to the toml configuration file as an argument, and if no value is given, it defaults to the openproxy.toml file in the execution path.

    The following options can be specified as command line arguments.

    • --log-target : Specifies the target pipeline for outputting log entries written by the OpenProxy process. Supported options are file, stdout, and both.

    • -l , --log-level : Defines the log level to be written. Supported levels are ERROR

    The above options can also be defined as environment variables. If environment variables and command line options are given together, the command line options take precedence.

    • LOG_TARGET : Corresponds to the log target.

    • LOG_LEVEL : Corresponds to the log level definition

    • MAX_LOGFILE_NUM : Corresponds to the maximum number of log files to keep.

    In addition to this, you can print help or view version or revision information


    You can utilize the administrator features by connecting to the OpenProxy node with the PostgreSQL user admin using the openproxy database name. It provides functions such as viewing configuration and currently active pools, checking stat information, etc.

    This is the number of worker threads in the asynchronous runtime that are launched when the program is executed. It is recommended to set this to match the number of CPU cores.

    connect_timeout

    Number

    1000

    Sets the timeout applied when connecting to the PostgreSQL server. The unit is milliseconds (ms).

    idle_timeout

    Number

    600000

    Specifies the idle timeout for connections created to the PostgreSQL server. The unit is milliseconds (ms). If the server connection is not used during this time, the connection is terminated.

    server_lifetime

    Number

    3600000

    Specifies the maximum lifetime of connections created to the PostgreSQL server. The unit is milliseconds (ms). Connections created will be terminated after this time, even if they are still in use.

    idle_client_in_transaction_timeout

    Number

    0

    Specifies the maximum idle timeout value for client transactions. The unit is milliseconds (ms). If set to 0, the timeout is not applied.

    healthcheck_timeout

    Number

    1000

    The timeout for health check messages sent to the PostgreSQL server is in milliseconds. If the PostgreSQL server does not respond within that time, OpenProxy bans the server from the pool and does not send any queries.

    healthcheck_delay

    Number

    30000

    Specify the interval for performing health checks on the PostgreSQL server. The unit is milliseconds (ms). If there is no activity on the server during this time, a health check is performed.

    shutdown_timeout

    Number

    60000

    When the OpenProxy process receives a SIGINT signal and shuts down gracefully, if there are any connected clients, it waits for the client connections to terminate during that time, which is measured in milliseconds.

    ban_time

    Number

    60

    If a PostgreSQL server fails the health check, it will be banned from the pool for the specified time in seconds. Once the banned PostgreSQL server has been banned for the specified time, it will be included in the pool again and become subject to the health check.

    tcp_keepalives_idle

    Number

    5

    If the TCP socket that maintains the connection created to the PostgreSQL server is idle for the specified period of time, it begins sending keepalive packets periodically to check the status. The unit is seconds (sec).

    tcp_keepalives_interval

    Number

    5

    The unit for the interval at which keepalive packets are sent is seconds (sec).

    tcp_keepalives_count

    Number

    5

    If the PostgreSQL server does not receive a response to the specified number of Keepalive packets sent periodically, the TCP connection is terminated.

    auth_type

    Enum

    md5

    Specifies the PostgreSQL password authentication method to use for client authentication. Supports the md5 and scram-sha-256 options.

    prepared_statements_cache_size

    Number

    0

    This option is only valid when using Transaction mode Pooling. It enables a global cache to store Prepared Statements sent from the Client and specifies the size of the cache. This option must be enabled to process Prepared Statements in Transaction pool mode. Prepared statements use OpenProxy memory and PostgreSQL resources, so it is recommended not to set this value too large.

    admin_username

    String

    -

    This is the admin username for managing OpenProxy

    admin_userpassword

    String

    -

    This is the password for the admin user used to manage OpenProxy.

    server_tls

    Bool

    false

    The TLS connection to the PostgreSQL server is enabled in OpenProxy. PostgreSQL must also be configured to accept TLS connections.

    verify_server_certificate

    Bool

    false

    If server_tls is enabled, verify that the server certificate is valid. Disallow connections to “self signed certificates” that are not stored in the root store where Openproxy is running.

    renew_interval

    Number

    5000

    Specifies the period for reloading TOML configuration files and updating the primary/replica status of nodes in shards managed by Patroni..

    reload_toml

    Bool

    true

    Specifies the period for reloading TOML configuration files and updating the primary/replica status of nodes in shards managed by Patroni.

    dns_cache_enabled

    Bool

    false

    If enabled, resolves and caches the DNS for the Openproxy PostgreSQL server (overriding the default TTL provided by system DNS servers). This is useful when routing PostgreSQL servers via DNS. If the cached value obtained from a DNS query has changed, the connection pool automatically creates a new connection to the new PostgreSQL server.

    dns_mas_ttl

    Number

    30

    The time for which cached DNS values are stored. If they expire, DNS refresh begins.

    -

    Virtual router IDs can have values from 1 to 255. They are used to distinguish virtual router clusters within the same network.

    priority

    Number

    -

    The priority value of the virtual router ranges from 0 to 255.

    advert_int

    Number

    -

    The interval is in seconds. VRRP advertisement packets are sent at the specified interval.

    vip_addresses

    Array

    -

    List of virtual IP addresses to be occupied.

    The format should be [“192.168.35.200/24“,”192.168.35.201/24"], separated by commas, and IPv4 addresses including the netmask bit length must be provided.

    pre_promote_script

    String

    -

    Optional.

    You can specify the OS command to execute before virtual IP occupation when BACKUP→MASTER promotion occurs.

    pre_demote_script

    String

    -

    Optional.

    You can specify the OS command to execute before releasing the virtual IP when MASTER→BACKUP demotion occurs.

    unicast_peers

    Array

    -

    Optional. If the network environment does not support multicast, VRRP packets can be sent in unicast mode, and the IPv4 addresses of all peer virtual router nodes are entered in an array format separated by commas, such as [“192.168.0.6", “192.168.0.8”].

    random

    Specifies the load balancing algorithm for replica nodes and supports random and loc. Random uses a random number generator to decide which replica to use. Loc selects the replica with the fewest connections being processed.

    query_parser_enabled

    Bool

    false

    Using the Rust library sqlparser, all queries requested by OpenProxy are parsed. This variable is used by the pooler to separate queries into read/write or extract sharding keys.

    query_parser_read_write_splitting

    Bool

    false

    When enabled, read queries are assigned to standby and write queries are assigned to primary.

    primary_reads_enabled

    Bool

    false

    When query_parser_enabled and query_parser_read_write_splitting are enabled together, read queries are distributed to the primary as well as the replica.

    idle_timeout

    Number

    -

    Reset the idle_timeout value in General settings for this pool.

    connect_timeout

    Number

    -

    Reset the connect_timeout value in General settings for this Pool unit.

    -

    The user's password. Only MD5 authentication is supported, so the client must provide a password that matches this.

    pool_size

    Number

    -

    The maximum number of connections to PostgreSQL.

    min_pool_size

    Number

    0

    This is the minimum number of PostgreSQL connections to keep open in the pool. Specifying this value reduces the cold start time when new clients connect. Setting this value too high relative to the load can increase the number of PostgreSQL connections, wasting server resources and preventing other pools from using them.

    statement_timeout

    Number

    0

    The maximum time (in milliseconds) to wait for the server to respond to the client's query. This feature is implemented in the PostgreSQL server and is not normally used, but can be used if PostgreSQL is unstable.

    pool_mode

    Enum

    -

    Resets the pool_mode value of [pools.pool_name].

    server_lifetime

    Number

    -

    Reset the server_lifetime value in General settings.

    None

    Set the cluster db-server address information to be accessed in array format. host/IP, port, role (primary, replica, Auto)

    (Example)

    servers = [ ["10.0.0.1", 5432,

    "primary"],

    ["replica-1.internal- dns.net", 5432, "replica"],

    ]

    use_patroni

    Bool

    false

    To use vip-failover, set it to true.

    ,
    WARN
    ,
    INFO
    ,
    DEBUG
    , and
    TRACE
    .
  • --max-logfile-num: Specifies the maximum number of log files to keep. Excess log files are automatically deleted from disk.

  • --log-dir: Enter the directory path to write log files to.

  • --log-format: Specifies the format of the log entries to be written. text, structured, debug option is also supported.

  • LOG_DIR : Corresponds to the directory path to write log files to.

  • LOG_FORMAT : Corresponds to the log entry format.

  • host

    String

    0.0.0.0

    The host address bound when the OpenProxy process starts.

    port

    Number

    6432

    It is the port bound when the OpenProxy process starts.

    worker_threads

    Number

    interface

    String

    -

    The network interface name of the host on which to register the virtual IP.

    router_id

    pool_mode

    Enum

    transaction

    The pooling mode of OpenProxy is set in this pool unit and supports session mode and transaction mode. In session mode, one PostgreSQL server connection is provided for each client connection, while in transaction mode, each client transaction is divided and processed across multiple PostgreSQL server connections.

    load_balancing_mode

    username

    String

    -

    The username

    password

    database

    String

    None

    This is the name of the database connected to PostgreSQL.

    servers

    Virtual Router

    Pools

    Users

    Shards

    Example of Configuration

    Execution

    Execute with CLI

    Defining it as a Systemd service

    View function

    View Version

    View Configuration

    View Database

    View Pool

    View Client

    View Server

    View User

    View List

    View Stat

    5

    Number

    Enum

    String

    Array

    [general]
    port = 6432
    admin_username = "postgres"
    admin_password = "postgres"
    autoreload = 5000
    worker_threads = 3
    
    [pools.postgres]
    pool_mode = "transaction"
    query_parser_enabled = true
    query_parser_read_write_splitting = true
    
    [pools.postgres.users.0]
    username = "postgres"
    password = "postgres"
    server_username = "postgres"
    server_password = "postgres"
    pool_size = 10
    statement_timeout = 0
    
    [pools.postgres.shards.0]
    database = "postgres"
    servers = [
      ["172.176.0.2", 5432, "auto"],
      ["172.176.0.3", 5432, "auto"],
      ["172.176.0.4", 5432, "auto"]
    ]
    use_patroni = true
    
    ## virtual-ip
    [general.virtual_router]
    interface = "eth0"
    router_id = 50
    priority = 50
    advert_int = 3
    vip_addresses = ["178.176.0.200/24"]
    $ ./openproxy /home/myUser/openproxy.toml
    $ openproxy --help
    OpenProxy: PostgreSQL pooler for OpenSQL - fork of pgCat
    
    Usage: openproxy [OPTIONS] [CONFIG_FILE]
    
    Arguments:
      [CONFIG_FILE]  [env: CONFIG_FILE=] [default: openproxy.toml]
    
    Options:
          --log-target <LOG_TARGET>
              [env: LOG_TARGET=] [default: both] [possible values: file, stdout, both]
      -l, --log-level <LOG_LEVEL>
              [env: LOG_LEVEL=] [default: INFO]
          --max-logfile-num <MAX_LOGFILE_NUM>
              [env: MAX_LOGFILE_NUM=] [default: 5]
          --log-dir <LOG_DIR>
              [env: LOG_DIR=] [default: logs]
          --revision
              Print revision number
      -F, --log-format <LOG_FORMAT>
              [env: LOG_FORMAT=] [default: text] [possible values: text, structured, debug]
      -h, --help
              Print help
      -V, --version
              Print version
    $ openproxy --help
    
    $ openproxy --version
    openproxy 0.0.2-OpenSQL-dev
    
    $ openproxy --revision
    revision number: 623
    [Unit]
    Description=OpenProxy connection pooler - fork of postgresml's pgcat
    After=network.target
    StartLimitIntervalSec=0
    
    [Service]
    User=opensql
    Type=simple
    Restart=always
    RestartSec=1
    Environment=LOG_LEVEL=info
    LimitNOFILE=65536
    AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
    ExecStart=/usr/bin/openproxy /etc/openproxy.toml
    
    [Install]
    WantedBy=multi-user.target
    $ psql -h 127.0.0.1 -p 6432 -d openproxy -U postgres
    openproxy=> SHOW HELP;
    NOTICE:  Console usage
    DETAIL:  
    	SHOW HELP|CONFIG|DATABASES|POOLS|CLIENTS|SERVERS|USERS|VERSION
    	SHOW LISTS
    	SHOW STATS
    	SET key = arg
    	RELOAD
    	PAUSE [<db>, <user>]
    	RESUME [<db>, <user>]
    	SHUTDOWN
    openproxy=> SHOW VERSION;
             version         
    -------------------------
     OpenProxy 1.0.0
    (1 row)
    openproxy=> SHOW CONFIG;
                           key                        |     value      | default | changeable 
    --------------------------------------------------+----------------+---------+------------
     idle_client_in_transaction_timeout               | 30000          | -       | yes
     pools."postgres".users                           | postgres       | -       | yes
     prometheus_exporter_port                         | 9930           | -       | yes
     pools.postgres.query_parser_max_length           | unlimited      | -       | yes
     pools.postgres.load_balancing_mode               | random         | -       | yes
     pools."postgres".shard_count                     | 1              | -       | yes
     port                                             | 6432           | -       | no
     connect_timeout                                  | 1000           | -       | no
     healthcheck_timeout                              | 1000           | -       | yes
     pools.postgres.default_role                      | any            | -       | yes
     healthcheck_delay                                | 30000          | -       | yes
     pools.postgres.query_parser_read_write_splitting | true           | -       | yes
     pools.postgres.sharding_function                 | pg_bigint_hash | -       | yes
     ban_time                                         | 60             | -       | yes
     pools.postgres.pool_mode                         | transaction    | -       | yes
     shutdown_timeout                                 | 60000          | -       | yes
     host                                             | 0.0.0.0        | -       | no
     pools.postgres.primary_reads_enabled             | false          | -       | yes
     idle_timeout                                     | 600000         | -       | yes
     pools.postgres.query_parser_enabled              | true           | -       | yes
    (20 rows)
    openproxy=> SHOW DATABASES;
                name            |      host      | port | database | force_user | pool_size | min_pool_size | reserve_pool |  pool_mode  | max_connections | current_connections | paused | disabled 
    ----------------------------+----------------+------+----------+------------+-----------+---------------+--------------+-------------+-----------------+---------------------+--------+----------
     postgres_shard_0_primary   | 192.168.131.12 | 5432 | postgres | postgres   |      1100 |             0 |            0 | transaction |            1100 |                   0 |      0 |        0
     postgres_shard_0_replica_0 | 192.168.131.13 | 5432 | postgres | postgres   |      1100 |             0 |            0 | transaction |            1100 |                   0 |      0 |        0
     postgres_shard_0_replica_1 | 192.168.131.14 | 5432 | postgres | postgres   |      1100 |             0 |            0 | transaction |            1100 |                   0 |      0 |        0
    (3 rows)
    openproxy=> SHOW POOLS;
     database  |    user     |  pool_mode  | cl_idle | cl_active | cl_waiting | cl_cancel_req | sv_active | sv_idle | sv_used | sv_tested | sv_login | maxwait | maxwait_us 
    -----------+-------------+-------------+---------+-----------+------------+---------------+-----------+---------+---------+-----------+----------+---------+------------
     simple_db | simple_user | session     |       0 |         0 |          0 |             0 |         0 |       0 |       0 |         0 |        0 |       0 |          0
     postgres  | postgres    | transaction |       0 |         0 |          0 |             0 |         0 |       3 |       0 |         0 |        0 |       0 |          0
    (2 rows)
    openproxy=> SHOW CLIENTS;
     client_id  | database |   user   | application_name | state | transaction_count | query_count | error_count | age_seconds | maxwait | maxwait_us 
    ------------+----------+----------+------------------+-------+-------------------+-------------+-------------+-------------+---------+------------
     0x43332945 | postgres | postgres | openproxy        | idle  |                 8 |           8 |           0 |           9 |       0 |          8
     0x993A6EA2 | postgres | postgres | openproxy        | idle  |                10 |          10 |           0 |           9 |       0 |          8
     0x09CFDA65 | pgcat    | postgres | psql             | idle  |                 0 |           0 |           0 |         208 |       0 |          0
     0x1E5A084D | postgres | postgres | openproxy        | idle  |                10 |          10 |           0 |           4 |       0 |          9
    (4 rows)
    openproxy=> SHOW SERVERS;
     server_id  | database_name |   user   |        address_id        |           application_name           | state | transaction_count | query_count | bytes_sent | bytes_received | age_seconds | prepare_cache_hit | prepare_cache_miss | prepare_cache_eviction | prepare_cache_size 
    ------------+---------------+----------+--------------------------+--------------------------------------+-------+-------------------+-------------+------------+----------------+-------------+-------------------+--------------------+------------------------+--------------------
     0x342F491B | postgres      | postgres | postgres_shard_0_primary | DBeaver 22.3.4 - SQLEditor <Console> | idle  |                41 |          41 |      18760 |         302727 |          25 |               123 |                 82 |                      0 |                 41
    (1 row)
    openproxy=> SHOW USERS;
       name   |  pool_mode  
    ----------+-------------
     postgres | transaction
    (1 row)
    openproxy=> SHOW LISTS;
         list      | items 
    ---------------+-------
     databases     |     4
     users         |     2
     pools         |     4
     free_clients  |     4
     used_clients  |     0
     login_clients |     0
     free_servers  |     1
     used_servers  |     0
     dns_names     |     0
     dns_zones     |     0
     dns_queries   |     0
     dns_pending   |     0
    (12 rows)
    openproxy=> SHOW STATS;
              instance          | database |   user   | total_xact_count | total_query_count | total_received | total_sent | total_xact_time | total_query_time | total_wait_time | total_errors | avg_xact_count | avg_query_count | avg_recv | avg_sent | avg_errors | avg_xact_time | avg_query_time | avg_wait_time 
    ----------------------------+----------+----------+------------------+-------------------+----------------+------------+-----------------+------------------+-----------------+--------------+----------------+-----------------+----------+----------+------------+---------------+----------------+---------------
     postgres_shard_0_primary   | postgres | postgres |               41 |                41 |         302727 |      18760 |               0 |               39 |           14152 |            0 |              0 |               0 |        0 |        0 |          0 |             0 |              0 |             0
     postgres_shard_0_replica_0 | postgres | postgres |                0 |                 0 |              0 |          0 |               0 |                0 |               0 |            0 |              0 |               0 |        0 |        0 |          0 |             0 |              0 |             0
     postgres_shard_0_replica_1 | postgres | postgres |                0 |                 0 |              0 |          0 |               0 |                0 |               0 |            0 |              0 |               0 |        0 |        0 |          0 |             0 |              0 |             0
    (3 rows)