Programming Language Integration

This document describes how to connect to YMatrix and perform queries using various programming languages. Both high-availability (HA) and non-HA connection methods are provided.

High Availability (HA) refers to YMatrix's automatic failover mechanism, where the Standby Master takes over service if the primary Master fails.

HA Connection means that after a failover event in YMatrix, the application automatically reconnects to the new active node.

HA Connection URLs / DSN provide a standardized format for use across applications without re-entering full connection details.
It typically consists of multiple fields, each representing different connection parameters, for example:
postgres://username:password@master_ip:master_port,standby_ip:standby_port/database?sslmode=disable

Where:

  • username and password are the username and password used to log in to the database.
  • master_ip:master_port and standby_ip:standby_port contain connection information for the Master and Standby nodes.
  • database specifies the target database name.
  • sslmode indicates whether SSL is enabled.

Note!
YMatrix supports high-speed data ingestion via the MatrixGate API. For more information, see Programming Language Integration with MatrixGate.


Create an example user ymatrix with password 1234.

=# CREATE USER ymatrix PASSWORD '1234';  
  • Master IP: 172.16.100.81; Port: 5432
  • Standby IP: 172.16.100.82; Port: 5432
  • Database: ymatrixdb


1 Java (High Availability)

Use the official PostgreSQL JDBC Driver as the database connector.

package com.postgresqltutorial;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class App{
    private final String url = "jdbc:postgres://ymatrix:[email protected]:5432,172.16.100.82:5432/ymatrixdb?sslmode=disable";
    private final String user = "ymatrix";
    private final String password = "1234";
    /**
     * Connect to the YMatrix database
     *
     * @return a Connection object
     */
    public Connection connect() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
            System.out.println("Connected to the YMatrix server successfully.");
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return conn;
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        App app = new App();
        app.connect();
    }
}


2 Python (High Availability)

Use psycopg 2/3 as the database connector.

# -*- coding: utf-8 -*-
import psycopg2

class YMatrix(object):
    def __init__(self):
        self.dsn = "postgres://ymatrix:[email protected]:5432,172.16.100.82:5432/ymatrixdb?sslmode=disable"

    def get_conn(self):
        conn = psycopg2.connect(dsn=self.dsn)
        return conn

    def create_table(self):
        conn = self.get_conn()
        cursor = conn.cursor()
        sql = "CREATE TABLE data(" \
              "time timestamp," \
              "tag_id int," \
              "metrics1 float8," \
              "metrics2 float8," \
              "metrics3 float8" \
              ")USING MARS3" \
              "DISTRIBUTED BY (tag_id)" \
              "ORDER BY (tag_id)"
        cursor.execute(sql)
        conn.commit()
        conn.close()

    def insert(self):
        conn = self.get_conn()
        cursor = conn.cursor()
        sql = "INSERT INTO data VALUES(now(), 1, 1.1, 1.2, 1.3)"
        cursor.execute(sql)
        conn.commit()
        conn.close()

    def select(self):
        conn = self.get_conn()
        cursor = conn.cursor()
        sql = "SELECT * FROM data"
        cursor.execute(sql)
        data = cursor.fetchone()
        conn.commit()
        conn.close()
        return data

if __name__ == '__main__':
    mxdb = YMatrix()
    mxdb.create_table()
    mxdb.insert()
    print(mxdb.select())


3 Golang (High Availability)

Use pgx as the database connector.

package main

import (
    "context"
    "fmt"
    "github.com/jackc/pgx/v4"
)

func main() {
    // Build connection configuration
    dsn := "postgres://ymatrix:<password>@172.16.100.81:5432,172.16.100.82:5432/ymatrixdb?sslmode=disable"
    config, err := pgx.ParseConfig(dsn)
    if err != nil {
        fmt.Println("Unable to parse config:", err)
        return
    }
    // Connect to the database
    conn, err := pgx.ConnectConfig(context.Background(), config)
    if err != nil {
        fmt.Println("Unable to connect to database:", err)
        return
    }
    defer conn.Close(context.Background())
}


4 Ruby (High Availability)

Use Ruby 3.3.3 or later.

4.1 Install Driver

Use ruby-pg as the database connector.

gem install pg -v 1.3.5 -- --with-pg-config=/opt/ymatrix/matrixdb5/bin/pg_config
Fetching pg-1.3.5.gem
Building native extensions with: '--with-pg-config=/opt/ymatrix/matrixdb5/bin/pg_config'
This could take a while...
Successfully installed pg-1.3.5
Parsing documentation for pg-1.3.5
Installing ri documentation for pg-1.3.5
Done installing documentation for pg after 1 seconds
1 gem installed

4.2 Programming

require 'pg'
# Build connection configuration
dsn = "postgres://ymatrix:[email protected]:5432,172.16.100.82:5432/ymatrixdb?sslmode=disable"
conn = PG.connect(dsn)
# Execute database operations
begin
  conn.exec('SELECT * FROM table_name') do |result|
    result.each do |row|
      # Process each row
      puts row.inspect
    end
  end
rescue PG::Error => e
  puts "An error occurred during database operation: #{e.message}"
ensure
  # Close connection
  conn.close if conn
end


5 Rust (High Availability)

Use rust-postgres as the database connector.

use postgres::{Client, Error, NoTls};
fn main() -> Result<(), Error> {
    let mut client = Client::connect(
        "postgresql://ymatrix:[email protected]:5432,172.16.100.82:5432/ymatrixdb",
        NoTls,
    )?;
    for row in client.query("SELECT * FROM table_name", &[])? {
        let id: i32 = row.get(0);
        let name: String = row.get(1);
        println!("ID: {}, Name: {}", id, name);
        // Perform required data processing here
    }
    Ok(())
}


6 C# (High Availability)

Use npgsql as the database connector.

C#
using System;
using Npgsql;
class Program
{
    static void Main()
    {
        // Configure HA DSN
        var connectionString = "Host=sdw1, sdw2;Port=5432;Database=mydatabase;Username=myuser;Password=mypassword;Load Balance Hosts=true";
        // Create connection
        using var connection = new NpgsqlConnection(connectionString);
        try
        {
            // Open connection
            connection.Open();
            // Execute query
            using var command = new NpgsqlCommand("SELECT * FROM table_name", connection);
            using var reader = command.ExecuteReader();
            // Process results
            while (reader.Read())
            {
                // Handle each row
                var column1Value = reader.GetString(0);
                var column2Value = reader.GetInt32(1);
                Console.WriteLine($"{column1Value}, {column2Value}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred: {ex.Message}");
        }
    }
}


7 C / C++ (High Availability)

Use ODBC as the database connector.

Note!
All commands below must be executed as root or with sudo privileges.

Download and install ODBC.

# yum install -y unixODBC.x86_64  
# yum install -y postgresql-odbc.x86_64  

Edit ODBC configuration files.

# cat /usr/local/etc/odbcinst.ini  
[PostgreSQL]  
Description = ODBC for PostgreSQL  
Driver      = /usr/lib/psqlodbcw.so  
Setup       = /usr/lib/libodbcpsqlS.so  
Driver64    = /usr/lib64/psqlodbcw.so  
Setup64     = /usr/lib64/libodbcpsqlS.so  
FileUsage = 1  

# cat /usr/local/etc/odbc.ini  
[pg]  
Description = Test to pg  
Driver = PostgreSQL  
Database = test  
// Replace content within "<>" with actual cluster info and remove "<>" symbols  
Servername = <Master,Standby>  
UserName = mxadmin  
Password = mxadmin  
Port = <Master Port,Standby Port>  
ReadOnly = 0  

Edit C/C++ source file.

# cat test.c  

#include <stdio.h>  
#include <sql.h>  
#include <sqlext.h>  
#include <string.h>  
#include <sqltypes.h>  

int main()  
{  
    SQLHENV henv;  
    SQLHDBC hdbc;  
    SQLHSTMT hstmt;  
    SQLRETURN ret;  

    // Allocate environment handle  
    ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);  
    // Set environment attribute  
    ret = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);  
    // Allocate connection handle  
    ret = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);  
    // Connect to database  
    ret = SQLConnect(hdbc, "pg", SQL_NTS, "mxadmin", SQL_NTS, "mxadmin", SQL_NTS);  
    if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)  
    {  
        printf("Connected to PostgreSQL database successfully.\n");  

        // Create table; replace <tablename> with actual name  
        ret = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);  
        ret = SQLExecDirect(hstmt, "CREATE TABLE <tablename> (id int) USING MARS3 DISTRIBUTED BY (id) ORDER BY (id)", SQL_NTS);  
        if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO)  
        {  
                printf("Table <tablename> created successfully.\n");  
        }  
        // Disconnect from database  
        SQLDisconnect(hdbc);  
    }  
    else  
    {  
        printf("Failed to connect to PostgreSQL database.\n");  
    }  
    // Free handles  
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);  
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);  
    SQLFreeHandle(SQL_HANDLE_ENV, henv);  

    return 0;  
}  

Compile.

# gcc -lodbc -o test test.c  

Run.

# ./test  
Connected to PostgreSQL database successfully.  

Verify table creation.

=#  \d <tablename>  
              Table "public.test2"  
 Column |  Type   | Collation | Nullable | Default  
--------+---------+-----------+----------+---------  
 id     | integer |           |          |  
Distributed by: (id)  


8 Node.js (High Availability)

Use the postgres module as the database connector.

const postgres = require('postgres')

async function query() {
  // Create HA database connection
  const conn = postgres(`postgres://username:password@master,stanby:port/database?sslmode=disable`)
  try {
    // Execute SQL query
    const rows = await conn`SELECT id, name FROM users`
    rows.forEach(row => {
      console.log(`id: ${row.id}, name: ${row.name}`)
    })
  } catch (err) {
    console.error(err)
  } finally {
    // Close connection
    await conn.end()
  }
}

query()


9 PHP (High Availability)

Use PHP 7.4 or later.

9.1 Install Driver

Use php-pgsql as the database connector.

# 1. Generate configure script
[root@ymatrix] cd /root/php-7.4.9/ext/pgsql
[root@ymatrix] /usr/local/php74/bin/phpize

Configuring for:
PHP Api Version:         20190902
Zend Module Api No:      20190902
Zend Extension Api No:   320190902

# 2. Set environment variables and run configure
# Paths must point to the target PHP version and YMatrix installation
[root@ymatrix] ./configure --with-php-config=/usr/local/php74/bin/php-config --with-pgsql=/opt/ymatrix/matrixdb5/

# 3. Compile and install
[root@ymatrix] make & make install

Installing shared extensions:     /usr/local/php74/lib/php/extensions/no-debug-non-zts-20190902/

# 4. Verify installation
[root@ymatrix] ls /usr/local/php74/lib/php/extensions/no-debug-non-zts-20190902/

pgsql.so

9.2 Install pdo_pgsql

# 1. Generate configure script
[root@ymatrix] cd /root/php-7.4.9/ext/pdo_pgsql
[root@ymatrix] /usr/local/php74/bin/phpize

Configuring for:
PHP Api Version:         20190902
Zend Module Api No:      20190902
Zend Extension Api No:   320190902

# 2. Set environment variables and run configure
[root@ymatrix] ./configure --with-php-config=/usr/local/php74/bin/php-config --with-pgsql=/opt/ymatrix/matrixdb5/

# 3. Compile and install
[root@ymatrix] make & make install

Installing shared extensions:     /usr/local/php74/lib/php/extensions/no-debug-non-zts-20190902/

# 4. Verify installation
[root@ymatrix] ls /usr/local/php74/lib/php/extensions/no-debug-non-zts-20190902/

pdo_pgsql.so  pgsql.so

9.3 Configure and restart php-fpm

[root@ymatrix] echo "extension=pgsql.so" >> /usr/local/php74/etc/php.ini
[root@ymatrix] echo "extension=pdo_pgsql.so" >> /usr/local/php74/etc/php.ini
[root@ymatrix] systemctl restart php-fpm

9.4 Programming

<?php
  $host    = "host=172.16.100.81,172.16.100.82";
  $port    = "port=5432";
  $dbname   = "dbname=postgres";
  $credentials = "user=mxadmin password=mxadmin";
  $db = pg_connect( "$host $port $dbname $credentials" );
  if(!$db){
   echo "Error : Unable to open database\n";
  } else {
   echo "Opened database successfully\n";
  }
  $sql =<<<EOF
   CREATE TABLE COMPANY
   (ID INT PRIMARY KEY   NOT NULL,
   NAME      TEXT  NOT NULL,
   AGE      INT   NOT NULL,
   ADDRESS    CHAR(50),
   SALARY     REAL);
EOF;
  $ret = pg_query($db, $sql);
  if(!$ret){
   echo pg_last_error($db);
  } else {
   echo "Table created successfully\n";
  }
  pg_close($db);
?>


10 Perl (High Availability)

Use Perl 5 version 5.40.0 or later.

10.1 Install Perl DBI Module

# 1. Prepare package
[root@ymatrix] wget http://search.cpan.org/CPAN/authors/id/T/TI/TIMB/DBI-1.625.tar.gz
[root@ymatrix] tar xvfz DBI-1.625.tar.gz
[root@ymatrix] cd DBI-1.625

# 2. Compile and install
[root@ymatrix] perl Makefile.PL
[root@ymatrix] make
[root@ymatrix] make install

10.2 Install DBD-Pg Module

# 1. Prepare package
[root@ymatrix] wget http://search.cpan.org/CPAN/authors/id/T/TU/TURNSTEP/DBD-Pg-2.19.3.tar.gz
[root@ymatrix] tar xvfz DBD-Pg-2.19.3.tar.gz
[root@ymatrix] cd DBD-Pg-2.19.3

# 2. Compile and install
# When prompted for major version number, enter 12 and press Enter
# When prompted for minor version number, enter 0 and press Enter
# When prompted for patch version number, enter 0 and press Enter
[root@ymatrix] export POSTGRES_HOME="/opt/ymatrix/matrixdb5/"
[root@ymatrix] perl Makefile.PL
[root@ymatrix] make
[root@ymatrix] make install

10.3 Programming

#!/usr/bin/perl

use DBI;
use strict;

my $driver   = "Pg";
my $database = "postgres";
my $dsn = "DBI:$driver:dbname=$database;host=172.16.100.107,172.16.100.108;port=5432";
my $userid = "mxadmin";
my $password = "mxadmin";
my $dbh = DBI->connect($dsn, $userid, $password, { RaiseError => 1 })
   or die $DBI::errstr;
print "Opened database successfully\n";

my $stmt = qq(CREATE TABLE COMPANY
      (ID INT PRIMARY KEY     NOT NULL,
      NAME           TEXT    NOT NULL,
      AGE            INT     NOT NULL,
      ADDRESS        CHAR(50),
      SALARY         REAL););
my $rv = $dbh->do($stmt);
if($rv < 0) {
   print $DBI::errstr;
} else {
   print "Table created successfully\n";
}
$dbh->disconnect();