parnishkka
parnishkka

Reputation: 11

How to connect to H2 database through TCP using h2go package?

I have docker container with H2 database, I can connect to it using "Database" IDE feature, also can ping container host using DNS name inside my server container.

I'm using github.com/jmrobles/h2go package as database driver, so i tried (i deleted some unnessecary code):

package service

import (
    "fmt"
    "github.com/jmoiron/sqlx"
    _ "github.com/jmrobles/h2go"
    "github.com/sirupsen/logrus"
)

func (s *DataSourceService) ConnectToH2Db(dbHost, dbUsername, dbPassword, dbName string, dbPort int) (*sqlx.DB, error) {
    connectionData := fmt.Sprintf("h2://%v:%v@%v:%v/%v", dbUsername, dbPassword, dbHost, dbPort, dbName)
    logrus.Info(connectionData)
    conn, err := sqlx.Open("h2", connectionData)
    if err != nil {
        logrus.Info("open")
        return nil, err
    }
    if err = conn.Ping(); err != nil {
        logrus.Info("ping")
        return nil, err
    }
    return conn, nil
}

When trying to connect i got driver: bad connection and logrus printed open.

Thanks in advance for the answer.

I also tried to use postgres driver Here my code:

package main

import (
    "fmt"
    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
    "log"
)

func main() {
    log.Println("started")
    username := "242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6"
    password := "242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6"
    host := "localhost"
    port := "7899"
    dbname := "NEWDB1"
    connectionData := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=disable", username, password, host, port, dbname)
    //connectionData := fmt.Sprintf("host=%v port=%v user=%v password=%v dbname=%v sslmode=disable",
    //  host, port, username, password, dbname)
    conn, err := sqlx.Open("postgres", connectionData)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("connected to database")
    if err = conn.Ping(); err != nil {
        log.Fatal(err)
    }
    log.Println("ping")
    if err = conn.Close(); err != nil {
        log.Fatal(err)
    }
    log.Println("close")
}

But it gives me:

2024/06/05 16:30:41 started
connected to database
2024/06/05 16:30:41 runtime error: slice bounds out of range [:-4]

Upvotes: 1

Views: 106

Answers (1)

Markus W Mahlberg
Markus W Mahlberg

Reputation: 20712

Testsetup

The code is available at https://github.com/mwmahlberg/go-database-78579085

I checked your revised code with a docker-compose as follows:

.
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yaml
├── env
├── env-long
├── go.mod
├── go.sum
└── main.go

Below you will find their contents, README.md, LICENSE (WTFPL), go.mod, go.sum skipped for brevity.

Dockerfile

FROM golang:1.22-alpine
WORKDIR /app
COPY . .
RUN go build -o main .
ENTRYPOINT [ "/app/main" ]

docker-compose.yaml

volumes:
  data:
    driver: local
services:
  postgres:
    image: postgres:latest
    ports:
      - 7899:5432
    volumes:
      - data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "${USERNAME:-test}"]
      interval: 1m30s
      timeout: 30s
      retries: 5
      start_period: 30s
      start_interval: 5s
    environment:
      POSTGRES_DB: NEWDB1
      POSTGRES_USER: ${USERNAME:-test}
      POSTGRES_PASSWORD: ${PASSWORD:-test}
  app:
    depends_on:
      postgres:
        condition: service_healthy
    image: app:latest
    build:
      context: .
      dockerfile: Dockerfile
    command:
      - "-host=postgres"
      - "-port=5432"
      - "-username=${USERNAME:-test}"
      - "-password=${PASSWORD:-test}"

env

USERNAME=leiZie4oogha0Uoth8Johphi0wi6apeiCh8oosheithoDohs0airaeghiePiw5r
PASSWORD=leiZie4oogha0Uoth8Johphi0wi6apeiCh8oosheithoDohs0airaeghiePiw5r

env-long

PASSWORD=242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6
USERNAME=242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6

main.go

package main

import (
    "flag"
    "fmt"
    "log"

    "github.com/jmoiron/sqlx"
    _ "github.com/lib/pq"
)

var (
    host     string
    port     int
    dbname   string
    username string
    password string
)

func init() {
    flag.StringVar(&host, "host", "localhost", "host")
    flag.IntVar(&port, "port", 7899, "port")
    flag.StringVar(&dbname, "dbname", "NEWDB1", "dbname")
    flag.StringVar(&username, "username", "", "username")
    flag.StringVar(&password, "password", "", "password")
}

func main() {
    flag.Parse()
    log.Println("started")
    connectionData := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=disable", username, password, host, port, dbname)
    conn, err := sqlx.Open("postgres", connectionData)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("connected to database")
    if err = conn.Ping(); err != nil {
        log.Fatal(err)
    }
    log.Println("ping")
    if err = conn.Close(); err != nil {
        log.Fatal(err)
    }
    log.Println("close")
}

Results

During startup of docker compose --env-file env-long up, I get the following error:

postgres-1  | 2024-06-09 14:42:28.775 UTC [40] FATAL:  identifier too long at character 72
postgres-1  | 2024-06-09 14:42:28.775 UTC [40] DETAIL:  Identifier must be less than 64 characters.
postgres-1  | 2024-06-09 14:42:28.775 UTC [40] STATEMENT:  
postgres-1  |   UPDATE pg_class   SET relacl = (SELECT array_agg(a.acl) FROM  (SELECT E'=r/"242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6"' as acl   UNION SELECT unnest(pg_catalog.acldefault(    CASE WHEN relkind = 'S' THEN 's'          ELSE 'r' END::"char",10::oid)) ) as a)   WHERE relkind IN ('r', 'v', 'm', 'S')  AND relacl IS NULL;
postgres-1  | 
postgres-1  | child process exited with exit code 1

When I try to manually create said user, I get the following error:

postgres=# CREATE USER 242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6 WITH PASSWORD '242440313243303331324a282975402148443041534a4430448fcaad801291b2a314895c683585be5263a6d9852473771474dff653f1c278d6';
ERROR:  trailing junk after numeric literal at or near "242440313243303331324a"
LINE 1: CREATE USER 242440313243303331324a282975402148443041534a4430...

Setting the username to a 63 long string works as expected:

postgres=# CREATE USER leiZie4oogha0Uoth8Johphi0wi6apeiCh8oosheithoDohs0airaeghiePiw5r WITH PASSWORD 'leiZie4oogha0Uoth8Johphi0wi6apeiCh8oosheithoDohs0airaeghiePiw5r';
CREATE ROLE

Running docker compose --env-file env up after resetting the compose environment with docker compose down --volumes results in:

app-1       | 2024/06/09 14:46:23 started
app-1       | connected to database
app-1       | 2024/06/09 14:46:23 ping
app-1       | 2024/06/09 14:46:23 close

Conclusion

The problem is not in the go code, but in the database setup. Also, I never ever got the error runtime error: slice bounds out of range [:-4]. I assume there is code missing in your example.

Upvotes: 0

Related Questions