package
0.2.0
Repository: https://github.com/breeze0806/go-etl.git
Documentation: pkg.go.dev

# README

Guide for Developers of Database Storage

Database storage is a framework for database queries and SQL execution, serving as an abstraction for databases. Its underlying implementation relies on the database/sql interface of the Golang standard library.

Introduction to Database Storage

Database storage facilitates the querying and execution of SQL through the encapsulation of the database/sql DB struct from the Golang standard library. The db.go file provides a rich set of methods, including not only the original methods of the database/sql DB such as BeginTx, PingContext, QueryContext, and ExecContext but also FetchTable and FetchTableWithParam for retrieving table structures, FetchRecord and FetchRecordWithTx for fetching records from a table, and BatchExec, BatchExecWithTx, and BatchExecStmtWithTx for executing write operations.

However, for different databases, the implementation of database storage can vary based on the specific database dialect. This document will introduce how to implement the database dialect interface.

Introduction to the Database Dialect Interface

The prerequisite for implementing the dialect interface is that the corresponding database driver can implement the database/sql interface of the Golang standard library.

When implementing specifically, you can refer to the following directory structure. Here, MySQL is used as an example:

storage--database--mysql----+--config.go        
                            |--doc.go
                            |--field.go
                            |--source.go
                            |--table.go

Using this approach, we have currently implemented support for MySQL, PostgreSQL, and DB2.

Data Source Interface

// Dialect represents a database dialect.
type Dialect interface {
 Source(*BaseSource) (Source, error) // Data source
}

// Source represents a data source, including driver information, package information, configuration files, and connection information.
type Source interface {
 Config() *config.JSON   // Configuration information
 Key() string            // Generally, the connection information
 DriverName() string     // Driver name, used as the 1st parameter for sql.Open
 ConnectName() string    // Connection information, used as the 2nd parameter for sql.Open
 Table(*BaseTable) Table // Get the specific table structure interface
}

When implementing the Source interface, you can combine BaseSource to simplify the implementation. The Table method should return the specific table structure interface. Refer to the implementation in source.go of the MySQL package.

Additionally, the connection information relies on the configuration provided by Config. Currently, Config needs to be defined as follows to be compatible with the dbms package for implementing DataX plugins. Refer to the implementation in config.go of the MySQL package.

type Config struct {
 URL      string `json:"url"`      // Database URL, including database address and other parameters
 Username string `json:"username"` // Username
 Password string `json:"password"` // Password
}

Furthermore, you need to use the init function to register the specific dialect:

func init() {
 var d Dialect
 database.RegisterDialect(d.Name(), d)
}

Table Structure Interface

// Table represents a table structure.
type Table interface {
 fmt.Stringer

 Quoted() string   // Fully qualified quoted table name
 Instance() string // Instance name, e.g., database for MySQL
 Schema() string   // Schema name, e.g., username (schema name) for Oracle
 Name() string     // Table name, e.g., table for MySQL
 Fields() []Field  // Displays all columns
}

// FieldsFetcher is a supplementary interface for Table, used to specifically fetch all columns.
type FieldsFetcher interface {
 FetchFields(ctx context.Context, db *DB) error // Retrieves the specific columns
}

// FieldAdder is a supplementary interface for Table, used to add new columns to the table.
type FieldAdder interface {
 AddField(*BaseField) // Adds a specific column
}

// ExecParameter is a supplementary interface for Table, used to generate SQL statements for write operations.
type ExecParameter interface {
 ExecParam(string, *sql.TxOptions) (Parameter, bool)
}

When implementing the Table interface, you can combine BaseTable to simplify the implementation. The Fields method must return a collection of specific field interfaces for the corresponding database. Refer to the implementation in table.go of the MySQL package.

You can choose to implement either FetchFields or FieldAdder, but generally, FieldAdder is preferred. ExecParameter can be used to implement SQL statements for bulk inserts. For example, for MySQL, you can implement the replace into method for insertion. Currently, a universally applicable insert method is implemented by default, but for cases like using the gora driver for Oracle, the insert method may not be suitable.

// Parameter represents an execution parameter with a table, transaction mode, and SQL statement.
type Parameter interface {
 Table() Table                                 // Table or view
 TxOptions() *sql.TxOptions                    // Transaction mode
 Query([]element.Record) (string, error)       // SQL prepare statement
 Agrs([]element.Record) ([]any, error) // Prepare parameters
}

To implement the replace into method for insertion, you need to implement the Parameter interface. You can combine BaseParam to simplify the implementation. Refer to the implementation in table.go of the MySQL package.

Field Interface

// Field represents a database column.
type Field interface {
 fmt.Stringer

 Index() int                   // Index
 Name() string                 // Column name
 Quoted() string               // Quoted column name
 BindVar(int) string           // Placeholder symbol
 Select() string               // Select column name
 Type() FieldType              // Column type
 Scanner() Scanner             // Scanner, used to convert database data into a column
 Valuer(element.Column) Valuer // Valuer, used to convert a column into database data
}

When implementing the Field interface, you can combine BaseField to simplify the implementation. The Type() method must return the specific column type for the corresponding database. The Scanner must return the scanner for the corresponding database, and the Valuer must return the valuer for the corresponding database. Refer to the implementation in field.go of the MySQL package.

// ColumnType represents a column type, abstracting `sql.ColumnType` and facilitating the implementation of corresponding functions.
type ColumnType interface {
 Name() string                                   // Column name
 ScanType() reflect.Type                         // Scan type
 Length() (length int64, ok bool)                // Length
 DecimalSize() (precision, scale int64, ok bool) // Precision
 Nullable() (nullable, ok bool)                  // Nullability
 DatabaseTypeName() string                       // Database type name
}

// FieldType represents a field type.
type FieldType interface {
 ColumnType

 IsSupportted() bool // Checks if the type is supported
}

When implementing the FieldType interface, you can combine BaseFieldType to simplify the implementation. ColumnType is essentially an abstraction of sql.ColumnType. Refer to the implementation in field.go of the MySQL package.

// Scanner represents a column data scanner that converts database driver values into column data.
type Scanner interface {
 sql.Scanner

 Column() element.Column // Gets the column data
}

When implementing the Scanner interface, you can combine BaseFieldType to simplify the implementation. The role of the scanner is to convert the data read by the database driver into a single column of data. Refer to the implementation in field.go of the MySQL package.

// Valuer represents a valuer that converts corresponding data into a value for the database driver.
type Valuer interface {
 driver.Valuer
}

// ValuerGoType is an optional functionality for the Field, used to determine the Go type for the corresponding driver value.
// It returns the corresponding value for the driver's value, facilitating the determination by GoValuer.
type ValuerGoType interface {
 GoType() GoType
}

When implementing the Valuer interface, you can combine GoValuer to simplify the implementation. To use GoValuer, you need to implement the ValuerGoType interface at the database layer's Field level. The role of the valuer is to convert a single column of data into the data type used for writing by the database driver. Refer to the implementation in field.go of the MySQL package.

# Packages

Package db2 implements the Dialect of db2 database, supporting the corresponding database of db2 9.x+.
Package mysql implements the Dialect of mysql database, supporting the corresponding database of mysql 5.7+.
Package oracle implements the Dialect for Oracle databases, supporting Oracle 10.5+ corresponding databases.
Package postgres implements the Dialect for PostgreSQL databases, supporting PostgreSQL 8.0+ corresponding databases.
Package sqlserver implements the Dialect for SQL Server databases, supporting MSSQL 2005+ corresponding databases.

# Functions

NewBaseFetchHandler Create Basic Record Handler.
NewBaseField: Creates a new base field based on the column name and column type.
NewBaseFieldType: Gets the field type.
NewBaseParam Generate basic parameters through table and transaction parameters txOps.
NewBaseSource Generate a basic data source from the JSON configuration file conf.
NewBaseTable, acquire the basic table through instance name, schema name, and table name.
NewConfig retrieves the database connection configuration 'c' from a JSON configuration 'err' refers to an error where the JSON configuration cannot be converted into a database connection configuration.
NewDB Acquire Database Connection Pool from Data Source source.
NewGoValuer: Generates a new Valuer using the GoType, primarily done through the field 'f' and the incoming column value 'c'.
NewInsertParam Generate insert parameters through table and transaction parameters txOps.
NewSource Obtain the corresponding data source by the name of the database dialect.
NewTableQueryParam Generate table structure query parameters from Table.
Open can acquire a reusable database connection pool wrapper through the database name and JSON configuration conf, similar to a smart pointer.
RegisterDialect Registers a database dialect.
UnregisterAllDialects Unregisters all database dialects.

# Constants

Default Parameters.
Default Parameters.
Boolean type.
Byte stream type.
Float64 type.
Int64 type.
String type.
Time type.
Unknown type.
Write to Database Schema.

# Variables

Error indicating that the interface is not a ValuerGoType.

# Structs

BaseConfig is the configuration for the base table.
BaseConfigSetter is the setter for the base table configuration.
BaseFetchHandler Basic Record Handler Acquisition.
BaseField: Represents a basic field, primarily storing the column name and column type.
BaseFieldType: Represents the basic type of a field, embedding implementations for various database field types.
BaseParam Basic parameters, used to embed SQL parameters for various databases.
BaseScanner: Represents a basic scanner, embedding implementations for various database scanners.
BaseSource Basic data source for storing JSON configuration files Used to embed Source, facilitating the implementation of various database Fields.
BaseTable Basic table, used to embed implementations of various database tables.
Config is the basic configuration for database connections, typically used for sql.DB configurations.
DB User Maintains Database Connection Pool.
DBWrapper is a wrapper for database connection pools, used to reuse relevant database connection pools (from unit to instance: user).
GoValuer: Generates a Valuer using the GoType.
InsertParam Insert parameters.
ParameterOptions Options for parameters.
PoolConfig is the configuration for the database connection pool Generally, the maximum number of open connections should be the same as the maximum number of idle connections, otherwise it can lead to insufficient file resources due to unreleased connections.
TableQueryParam Table structure query parameters.

# Interfaces

ColumnType: Represents the type of a column, abstracting sql.ColumnType and facilitating custom implementations.
ConfigSetter is an additional method for Table, used to set the JSON configuration file.
Dialect Database Dialect.
ExecParameter Supplementary method for Table, used to get the method to generate SQL statements for write mode.
FetchHandler Acquire Record Handler.
Field refers to a database field.
FieldAdder Supplementary method for Table, used to add columns to a table.
FieldsFetcher Supplementary method for Table, used to specially fetch all columns of a table.
FieldType: Represents the type of a field.
Judger Error evaluator.
Parameter Execution parameters for SQL statements with table, transaction mode, and SQL.
Scanner: Data scanner for columns.
Source Data Source, containing driver information, package information, configuration files, and connection information.
Table Table structure.
Valuer: Converts corresponding data into database driver values.
No description provided by the author
WithConnector Data Source with Connection, the data source prefers to call this method to generate a data connection pool DB.

# Type aliases

GoType refers to the type in the Golang language.