entc: blob storage support

This commit is contained in:
Giau. Tran Minh
2026-05-18 17:07:16 +00:00
parent 477cecd0dc
commit 2d33420c0c
37 changed files with 1711 additions and 42 deletions

View File

@@ -135,6 +135,8 @@ func (d *MySQL) atTypeC(c1 *Column, c2 *schema.Column) error {
switch c1.Type {
case field.TypeBool:
t = &schema.BoolType{T: "boolean"}
case field.TypeBlob:
return fmt.Errorf("blob fields are not stored in the database")
case field.TypeInt8:
t = &schema.IntegerType{T: mysql.TypeTinyInt}
case field.TypeUint8:

View File

@@ -113,6 +113,8 @@ func (d *Postgres) atTypeC(c1 *Column, c2 *schema.Column) error {
}
var t schema.Type
switch c1.Type {
case field.TypeBlob:
return fmt.Errorf("blob fields are not stored in the database")
case field.TypeBool:
t = &schema.BoolType{T: postgres.TypeBoolean}
case field.TypeUint8, field.TypeInt8, field.TypeInt16:

View File

@@ -114,6 +114,8 @@ func (d *SQLite) atTypeC(c1 *Column, c2 *schema.Column) error {
}
var t schema.Type
switch c1.Type {
case field.TypeBlob:
return fmt.Errorf("blob fields are not stored in the database")
case field.TypeBool:
t = &schema.BoolType{T: "bool"}
case field.TypeInt8, field.TypeUint8, field.TypeInt16, field.TypeUint16, field.TypeInt32,

View File

@@ -0,0 +1,74 @@
// Copyright 2019-present Facebook Inc. All rights reserved.
// This source code is licensed under the Apache 2.0 license found
// in the LICENSE file in the root directory of this source tree.
package sqlgraph
import (
"context"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
)
// BlobSpec configures SQL-level blob key queries and implements [ent.BlobQuerier].
type BlobSpec struct {
Driver dialect.Driver
Table string
Columns map[string]string // field name -> key column name
Predicate func(*sql.Selector)
}
// QueryBlobKeys implements [ent.BlobQuerier].
// If fields is nil, all columns are queried (for deletes);
// otherwise only the named fields are queried.
func (s *BlobSpec) QueryBlobKeys(ctx context.Context, fields []string) ([]ent.BlobKey, error) {
cols := s.Columns
if len(fields) > 0 {
cols = make(map[string]string, len(fields))
for _, f := range fields {
if c, ok := s.Columns[f]; ok {
cols[f] = c
}
}
}
if len(cols) == 0 {
return nil, nil
}
names := make([]string, 0, len(cols))
colNames := make([]string, 0, len(cols))
for field, col := range cols {
names = append(names, field)
colNames = append(colNames, col)
}
selector := sql.Dialect(s.Driver.Dialect()).
Select(colNames...).
From(sql.Table(s.Table))
if s.Predicate != nil {
s.Predicate(selector)
}
query, args := selector.Query()
rows := &sql.Rows{}
if err := s.Driver.Query(ctx, query, args, rows); err != nil {
return nil, err
}
defer rows.Close()
var keys []ent.BlobKey
for rows.Next() {
vals := make([]*string, len(colNames))
ptrs := make([]any, len(colNames))
for i := range vals {
ptrs[i] = &vals[i]
}
if err := rows.Scan(ptrs...); err != nil {
return nil, err
}
for i, v := range vals {
if v != nil && *v != "" {
keys = append(keys, ent.BlobKey{Field: names[i], Key: *v})
}
}
}
return keys, rows.Err()
}