dynmgrm

package module
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 5, 2024 License: MIT Imports: 20 Imported by: 0

README

dynmgrm - GORM DynamoDB Driver

logo

Go Reference GitHub go.mod Go version (subdirectory of monorepo) GitHub release (latest by date) codecov Go Report Card GitHub License

dynmgrm is the driver to issue PartiQL Statement to DynamoDB with GORM⚡

Features

Supports the following PartiQL statements
  • Select
    • With Secondary Index
    • With begins_with function
    • With contains function
    • With size function
    • With attribute_type function
    • With MISSING operator
  • Insert
  • Update
    • With SET clause
      • With list_append function
        • ListAppend()
      • With set_add function
      • With set_delete function
    • With REMOVE clause
  • Delete
  • Create Table ※ proprietary PartiQL syntax by miyamo2/godynamo
  • Create GSI ※ proprietary PartiQL syntax by miyamo2/godynamo
Supports the following GORM features
  • Query

    • Select
    • Find
    • Scan
  • Update

    • Update
    • Updates
    • Save
  • Create

    • Create
  • Delete

    • Delete
  • Condition

    • Where
    • Not
    • Or
  • Table/Model

    • Table
    • Model ※ Combination with Secondary Index are not supported.
  • Transaction ※ Supports only Insert, Update, and Delete.

    • Begin
    • Commit
    • Rollback
    • Transaction
  • Migration

    • AutoMigrate
    • CurrentDatabase
    • FullDataTypeOf
    • CreateTable
    • DropTable
    • HasTable
    • GetTables
    • HasColumn
    • ColumnTypes
    • CreateIndex
    • DropIndex
    • HasIndex
Custom Clause
  • SecondaryIndex
Custom Serializer
  • dynamo-nested

What is about GORM Serializer?

Quick Start

Installation
go get github.com/miyamo2/dynmgrm
Usage

[!TIP]

miyamo2/dynmgrm is recommended to be used in with miyamo2/sqldav.

miyamo2/sqldav provides Defined Type of slice/map that implements sql.Scanner and driver.Valuer.

These are as the equivalent to Set, List, Map and TypedList included in miyamo2/dynmgrm before v0.9.0.

package main

import (
	"github.com/miyamo2/dynmgrm"
	"github.com/miyamo2/sqldav"
	"gorm.io/gorm"
)

type Event struct {
	Name  string `gorm:"primaryKey"`
	Date  string `gorm:"primaryKey"`
	Host  string
	Guest sqldav.Set[string]
}

func main() {
	db, err := gorm.Open(dynmgrm.New())
	if err != nil {
		panic(err)
	}

	var dynamoDBWorkshop Event
	db.Table("events").
		Where(`name=?`, "DynamoDB Workshop").
		Where(`date=?`, "2024/3/25").
		Scan(&dynamoDBWorkshop)

	dynamoDBWorkshop.Guest = append(dynamoDBWorkshop.Guest, "Alice")
	db.Save(&dynamoDBWorkshop)

	carolBirthday := Event{
		Name: "Carol's Birthday",
		Date: "2024/4/1",
		Host: "Charlie",
		Guest: []string{"Alice", "Bob"},
	}
	db.Create(carolBirthday)

	var daveSchedule []Event
	db.Table("events").
		Where(`date=?`, "2024/4/1").
		Where(`( ? )`,
			db.Where(`host=?`, "Dave").Or(`CONTAINS("guest", ?)`, "Dave")).
		Scan(&daveSchedule)

	tx := db.Begin()
	for _, event := range daveSchedule {
		if event.Host == "Dave" {
			tx.Delete(&event)
		} else {
			tx.Model(&event).Update("guest", gorm.Expr("set_delete(guest, ?)", sqldav.Set[string]{"Dave"}))
		}
	}
	tx.Model(&carolBirthday).Update("guest", gorm.Expr("set_add(guest, ?)", sqldav.Set[string]{"Dave"}))
	tx.Commit()

	var hostDateIndex []Event
	db.Table("events").Clauses(
		dynmgrm.SecondaryIndex("host-date-index"),
	).Where(`host=?`, "Bob").Scan(&hostDateIndex)
}

Contributing

Feel free to open a PR or an Issue.

However, you must promise to follow our Code of Conduct.

See here for more details on contributing.

License

dynmgrm released under the MIT License

Credits

Go gopher

The Go gopher was designed by Renee French. The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details

Special Thanks
  • btnguyen2k/godynamo

    dynmgrm connects to database/sql by miyamo2/godynamo that forked from btnguyen2k/godynamo.

  • JetBrainsMono

    JetBrainsMono is used for the caption of the dynmgrm logo.

Documentation

Overview

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
	"github.com/miyamo2/sqldav"
	"gorm.io/gorm"
)

type Event struct {
	Name  string `gorm:"primaryKey"`
	Date  string `gorm:"primaryKey"`
	Host  string
	Guest sqldav.Set[string]
}

func main() {
	db, err := gorm.Open(dynmgrm.New())
	if err != nil {
		panic(err)
	}

	var dynamoDBWorkshop Event
	db.Table("events").
		Where(`name=?`, "DynamoDB Workshop").
		Where(`date=?`, "2024/3/25").
		Scan(&dynamoDBWorkshop)

	dynamoDBWorkshop.Guest = append(dynamoDBWorkshop.Guest, "Alice")
	db.Save(&dynamoDBWorkshop)

	carolBirthday := Event{
		Name:  "Carol's Birthday",
		Date:  "2024/4/1",
		Host:  "Charlie",
		Guest: []string{"Alice", "Bob"},
	}
	db.Create(carolBirthday)

	var daveSchedule []Event
	db.Table("events").
		Where(`date=?`, "2024/4/1").
		Where(`( ? )`,
			db.Where(`host=?`, "Dave").Or(`CONTAINS("guest", ?)`, "Dave")).
		Scan(&daveSchedule)

	tx := db.Begin()
	for _, event := range daveSchedule {
		if event.Host == "Dave" {
			tx.Delete(&event)
		} else {
			tx.Model(&event).Update("guest", gorm.Expr("set_delete(guest, ?)", sqldav.Set[string]{"Dave"}))
		}
	}
	tx.Model(&carolBirthday).Update("guest", gorm.Expr("set_add(guest, ?)", sqldav.Set[string]{"Dave"}))
	tx.Commit()

	var hostDateIndex []Event
	db.Table("events").Clauses(
		dynmgrm.SecondaryIndex("host-date-index"),
	).Where(`host=?`, "Bob").Scan(&hostDateIndex)
}
Output:

Index

Examples

Constants

View Source
const (
	// DriverName is the driver name for DynamoDB.
	DriverName = "godynamo"
	DBName     = "dynamodb"
)

Variables

View Source
var ErrDynmgrmAreNotSupported = errors.New("dynmgrm are not supported this operation")
View Source
var ErrIncompatibleNestedStruct = errors.New("incompatible nested struct")

ErrIncompatibleNestedStruct occurs when an incompatible with nested-struct.

View Source
var (
	ErrInvalidColumnName = errors.New("column name contains invalid characters")
)

Functions

func ListAppend added in v0.5.0

func ListAppend(item ...interface{}) *listAppend

ListAppend returns a functionForPartiQLUpdates implementation for `list_append` function.

Example
db, err := gorm.Open(
	dynmgrm.New(),
	&gorm.Config{
		SkipDefaultTransaction: true,
	})
if err != nil {
	log.Fatalf("failed to open database, got error %v", err)
}
db.Model(&TestTable{PK: "Partition1", SK: 1}).
	Update("list_type_attr",
		dynmgrm.ListAppend(sqldav.Map{"Foo": "Bar"}))
Output:

func New

func New(option ...DialectorOption) gorm.Dialector

New returns a new DynamoDB dialector with options.

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.New())
}
Output:

Example (WithAccessKeyID)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.New(dynmgrm.WithAccessKeyID("YourAccess")))
}
Output:

Example (WithEndpoint)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.New(dynmgrm.WithEndpoint("http://localhost:8000")))
}
Output:

Example (WithRegion)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.New(dynmgrm.WithRegion("ap-northeast-1")))
}
Output:

Example (WithSecretKey)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.New(dynmgrm.WithSecretKey("YourSecretKey")))
}
Output:

Example (WithTimeout)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.New(dynmgrm.WithTimeout(30000)))
}
Output:

func Open

func Open(dsn string) gorm.Dialector

Open returns a new DynamoDB dialector based on the DSN.

e.g. "region=ap-northeast-1;AkId=<YOUR_ACCESS_KEY_ID>;SecretKey=<YOUR_SECRET_KEY>"

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

func main() {
	gorm.Open(dynmgrm.Open("region=ap-northeast-1;AkId=YourAccessKeyID;SecretKey=YourSecretKey"))
}
Output:

func SecondaryIndex

func SecondaryIndex(indexName string, options ...SecondaryIndexOption) secondaryIndexExpression

SecondaryIndex enables queries using a secondary index

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

type TestTable struct {
	PK     string `gorm:"primaryKey"`
	SK     int    `gorm:"primaryKey"`
	GSIKey string
}

func main() {
	db, err := gorm.Open(dynmgrm.New(), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	result := TestTable{}
	db.Table("something").Clauses(
		dynmgrm.SecondaryIndex("gsi_key-sk-index")).
		Where(`gsi_key = ?`, "1").
		Scan(&result)
}
Output:

Example (WithSecondaryIndexOf_withString)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
)

type TestTable struct {
	PK     string `gorm:"primaryKey"`
	SK     int    `gorm:"primaryKey"`
	GSIKey string
}

func main() {
	db, err := gorm.Open(dynmgrm.New(), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	result := TestTable{}
	db.Clauses(
		dynmgrm.SecondaryIndex("gsi_key-sk-index",
			dynmgrm.SecondaryIndexOf("something"))).
		Where(`gsi_key = ?`, "1").
		Scan(&result)
}
Output:

Example (WithSecondaryIndexOf_withTableClause)
package main

import (
	"github.com/miyamo2/dynmgrm"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type TestTable struct {
	PK     string `gorm:"primaryKey"`
	SK     int    `gorm:"primaryKey"`
	GSIKey string
}

func main() {
	db, err := gorm.Open(dynmgrm.New(), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	result := TestTable{}
	db.Clauses(
		dynmgrm.SecondaryIndex("gsi_key-sk-index",
			dynmgrm.SecondaryIndexOf(
				clause.Table{
					Name: "something",
				}))).
		Where(`gsi_key = ?`, "1").
		Scan(&result)
}
Output:

func WithAccessKeyID

func WithAccessKeyID(accessKeyId string) func(*config)

WithAccessKeyID sets the access key ID for the DynamoDB connection.

Default: https://github.com/miyamo2/godynamo?tab=readme-ov-file#data-source-name-dsn-format-for-aws-dynamodb

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
)

func main() {
	dynmgrm.WithAccessKeyID("YourAccess")
}
Output:

func WithConnection

func WithConnection(conn gorm.ConnPool) func(*config)

WithConnection sets the exist connection for the DynamoDB.

func WithEndpoint

func WithEndpoint(endpoint string) func(*config)

WithEndpoint sets the endpoint for the DynamoDB connection.

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
)

func main() {
	dynmgrm.WithEndpoint("http://localhost:8000")
}
Output:

func WithRegion

func WithRegion(region string) func(*config)

WithRegion sets the region for the DynamoDB connection.

Default: https://github.com/miyamo2/godynamo?tab=readme-ov-file#data-source-name-dsn-format-for-aws-dynamodb

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
)

func main() {
	dynmgrm.WithRegion("ap-northeast-1")
}
Output:

func WithSecretKey

func WithSecretKey(secretKey string) func(*config)

WithSecretKey sets the secret key for the DynamoDB connection.

Default: https://github.com/miyamo2/godynamo?tab=readme-ov-file#data-source-name-dsn-format-for-aws-dynamodb

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
)

func main() {
	dynmgrm.WithSecretKey("YourSecretKey")
}
Output:

func WithTimeout

func WithTimeout(timeout int) func(*config)

WithTimeout sets the timeout milliseconds for the DynamoDB connection.

Default: https://github.com/miyamo2/godynamo?tab=readme-ov-file#data-source-name-dsn-format-for-aws-dynamodb

Example
package main

import (
	"github.com/miyamo2/dynmgrm"
)

func main() {
	dynmgrm.WithTimeout(30000)
}
Output:

Types

type BaseMigrator added in v0.6.0

type BaseMigrator interface {
	gorm.Migrator
	RunWithValue(value interface{}, fc func(stmt *gorm.Statement) error) error
	CurrentTable(stmt *gorm.Statement) interface{}
}

type CallbacksRegisterer

type CallbacksRegisterer interface {
	Register(db *gorm.DB, config *callbacks.Config)
}

type CapacityUnitsSpecifier added in v0.6.0

type CapacityUnitsSpecifier interface {
	WCU() int
	RCU() int
}

CapacityUnitsSpecifier could specify WCUs and RCU

type DBForMigrator added in v0.6.0

type DBForMigrator interface {
	AddError(err error) error
	Exec(sql string, values ...interface{}) (tx *gorm.DB)
}

type DBOpener

type DBOpener interface {
	DSN() string
	DriverName() string
	Apply() (*sql.DB, error)
}

DBOpener is the interface for opening a database.

type Dialector

type Dialector struct {
	// contains filtered or unexported fields
}

Dialector gorm dialector for DynamoDB

func (Dialector) BindVarTo

func (dialector Dialector) BindVarTo(writer clause.Writer, stmt *gorm.Statement, v interface{})

BindVarTo writes the bind variable of goodynamo to clauses.Writer.

func (Dialector) DataTypeOf

func (dialector Dialector) DataTypeOf(field *schema.Field) string

DataTypeOf maps GORM's data types to DynamoDB's data types. DataTypeOf works only with migration, so it will not return data types that are not allowed in PK, SK.

func (Dialector) DefaultValueOf

func (dialector Dialector) DefaultValueOf(field *schema.Field) clause.Expression

DefaultValueOf returns the default value of the field.

func (Dialector) Explain

func (dialector Dialector) Explain(sql string, vars ...interface{}) string

Explain returns the SQL string with the variables replaced. Explain is typically used only for logging, dry runs, and migration.

func (Dialector) Initialize

func (dialector Dialector) Initialize(db *gorm.DB) (err error)

Initialize initializes the DynamoDB connection.

func (Dialector) Migrator

func (dialector Dialector) Migrator(db *gorm.DB) gorm.Migrator

Migrator returns the migrator for DynamoDB.

func (Dialector) Name

func (dialector Dialector) Name() string

Name returns the name of the db.

func (Dialector) QuoteTo

func (dialector Dialector) QuoteTo(writer clause.Writer, str string)

QuoteTo escapes identifiers in SQL queries

func (Dialector) Translate

func (dialector Dialector) Translate(err error) error

Translate it will translate the error to native gorm errors.

type DialectorOption

type DialectorOption func(*config)

DialectorOption is the option for the DynamoDB dialector.

type KeySchemaDataType added in v0.3.0

type KeySchemaDataType string

KeySchemaDataType is the data type for the DynamoDB key schema.

const (
	// KeySchemaDataTypeString is the data type for string.
	KeySchemaDataTypeString KeySchemaDataType = "string"
	// KeySchemaDataTypeNumber is the data type for number.
	KeySchemaDataTypeNumber KeySchemaDataType = "number"
	// KeySchemaDataTypeBinary is the data type for binary.
	KeySchemaDataTypeBinary KeySchemaDataType = "binary"
)

Define KeySchemaDataType

func (KeySchemaDataType) String added in v0.3.0

func (d KeySchemaDataType) String() string

String returns the string representation of the KeySchemaDataType.

type Migrator

type Migrator struct {
	// contains filtered or unexported fields
}

Migrator is gorm.Migrator implementation for dynamodb

func (Migrator) AddColumn deprecated

func (m Migrator) AddColumn(dst interface{}, field string) error

AddColumn See: [gorm.migrator.Migrator.AddColumn]

Deprecated: DynamoDB are schema less, so this operation is not supported.

func (Migrator) AlterColumn deprecated

func (m Migrator) AlterColumn(dst interface{}, field string) error

AlterColumn See: gorm.migrator.Migrator.AlterColumn

Deprecated: DynamoDB are schema less, so this operation is not supported.

func (Migrator) AutoMigrate

func (m Migrator) AutoMigrate(dst ...interface{}) error

func (Migrator) ColumnTypes

func (m Migrator) ColumnTypes(dst interface{}) ([]gorm.ColumnType, error)

func (Migrator) CreateConstraint deprecated

func (m Migrator) CreateConstraint(dst interface{}, name string) error

CreateConstraint See: gorm.migrator.Migrator.CreateConstraint

Deprecated: DynamoDB does not provide constraint feature, so this operation is not supported.

func (Migrator) CreateIndex

func (m Migrator) CreateIndex(dst interface{}, name string) error

func (Migrator) CreateTable

func (m Migrator) CreateTable(models ...interface{}) error

func (Migrator) CreateView deprecated

func (m Migrator) CreateView(name string, option gorm.ViewOption) error

CreateView See: gorm.migrator.Migrator.CreateView

Deprecated: DynamoDB does not provide View feature, so this operation is not supported.

func (Migrator) CurrentDatabase

func (m Migrator) CurrentDatabase() string

func (Migrator) DropColumn deprecated

func (m Migrator) DropColumn(dst interface{}, field string) error

DropColumn See: gorm.migrator.Migrator.DropColumn

Deprecated: DynamoDB are schema less, so this operation is not supported.

func (Migrator) DropConstraint deprecated

func (m Migrator) DropConstraint(dst interface{}, name string) error

DropConstraint See: gorm.migrator.Migrator.DropConstraint

Deprecated: DynamoDB does not provide constraint feature, so this operation is not supported.

func (Migrator) DropIndex

func (m Migrator) DropIndex(dst interface{}, name string) error

func (Migrator) DropTable

func (m Migrator) DropTable(dst ...interface{}) error

func (Migrator) DropView deprecated

func (m Migrator) DropView(name string) error

DropView See: gorm.migrator.Migrator.DropView

Deprecated: DynamoDB does not provide View feature, so this operation is not supported.

func (Migrator) FullDataTypeOf

func (m Migrator) FullDataTypeOf(field *schema.Field) clause.Expr

func (Migrator) GetIndexes

func (m Migrator) GetIndexes(dst interface{}) ([]gorm.Index, error)

func (Migrator) GetTables

func (m Migrator) GetTables() (tableList []string, err error)

func (Migrator) GetTypeAliases

func (m Migrator) GetTypeAliases(databaseTypeName string) []string

func (Migrator) HasColumn

func (m Migrator) HasColumn(dst interface{}, field string) bool

func (Migrator) HasConstraint deprecated

func (m Migrator) HasConstraint(dst interface{}, name string) bool

HasConstraint See: gorm.migrator.Migrator.HasConstraint

Deprecated: DynamoDB does not provide constraint feature, so this operation is not supported.

func (Migrator) HasIndex

func (m Migrator) HasIndex(dst interface{}, name string) bool

func (Migrator) HasTable

func (m Migrator) HasTable(dst interface{}) bool

func (Migrator) MigrateColumn deprecated

func (m Migrator) MigrateColumn(dst interface{}, field *schema.Field, columnType gorm.ColumnType) error

MigrateColumn See: gorm.migrator.Migrator.MigrateColumn

Deprecated: DynamoDB are schema less, so this operation is not supported.

func (Migrator) MigrateColumnUnique deprecated

func (m Migrator) MigrateColumnUnique(dst interface{}, field *schema.Field, columnType gorm.ColumnType) error

MigrateColumnUnique See: gorm.migrator.Migrator.MigrateColumnUnique

Deprecated: DynamoDB are schema less, so this operation is not supported.

func (Migrator) RenameColumn deprecated

func (m Migrator) RenameColumn(dst interface{}, oldName, field string) error

RenameColumn See: gorm.migrator.Migrator.RenameColumn

Deprecated: DynamoDB are schema less, so this operation is not supported.

func (Migrator) RenameIndex deprecated

func (m Migrator) RenameIndex(dst interface{}, oldName, newName string) error

RenameIndex See: gorm.migrator.Migrator.RenameIndex

Deprecated: DynamoDB does not possibly rename an existing index, so this operation is not supported.

func (Migrator) RenameTable deprecated

func (m Migrator) RenameTable(oldName, newName interface{}) error

RenameTable See: gorm.migrator.Migrator.RenameTable

Deprecated: DynamoDB does not possibly rename an existing table, so this operation is not supported.

func (Migrator) TableType

func (m Migrator) TableType(dst interface{}) (gorm.TableType, error)

type SecondaryIndexOption

type SecondaryIndexOption func(*secondaryIndexExpression)

SecondaryIndexOption is a functional option for secondaryIndexExpression

func SecondaryIndexOf

func SecondaryIndexOf[T string | clause.Table](table T) SecondaryIndexOption

SecondaryIndexOf is the table with the index to be used.

type TableClass added in v0.6.0

type TableClass int

TableClass is the type of table class

const (
	TableClassStandard TableClass = iota
	TableClassStandardIA
)

TableClassStandard and TableClassStandardIA are the supported table classes

func (TableClass) String added in v0.6.0

func (t TableClass) String() string

type TableClassSpecifier added in v0.6.0

type TableClassSpecifier interface {
	TableClass() TableClass
}

TableClassSpecifier could specify table class.

Directories

Path Synopsis
internal
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL