File size: 3,210 Bytes
fea99b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{{/*
    This template exposes client internals (like the driver) so they can be shared accross instances.
    The intended usecase is for shared transaction management accross multiple db.Client and db.Tx instances
    using the same connection.

    This template has to be included in each entgo codegen that wants to parttake in shared transactions.

    // TODO: Tx.onRollback and Tx.onCommit hooks are ignored when using shared transactions, fix this
*/}}
{{ define "expose" }}


{{/* Add the base header for the generated file */}}
{{ $pkg := base $.Config.Package }}
{{ template "header" $ }}

{{/* Expose internals of a Client so it can be used by transaction management */}}
func (c *Client) GetConfig() *entutils.RawEntConfig {
    return &entutils.RawEntConfig{
        Driver: c.config.driver,
        Debug: c.config.debug,
        Log: c.config.log,
    }
}
{{/* Expose internals of a Transactional Client so it can be used by transaction management */}}
// ignores hooks and intersectors
type ExposedTxDriver struct {
    Driver *txDriver
}

var _ entutils.Transactable = (*ExposedTxDriver)(nil)

func (d *ExposedTxDriver) Rollback() error {
    return d.Driver.tx.Rollback()
}

func (d *ExposedTxDriver) Commit() error {
    return d.Driver.tx.Commit()
}

func (d *ExposedTxDriver) SavePoint(name string) error {
	_, err := d.Driver.ExecContext(context.Background(), "SAVEPOINT " + name)
    return err
}

func (d *ExposedTxDriver) RollbackTo(name string) error {
	_, err := d.Driver.ExecContext(context.Background(), "ROLLBACK TO " + name)
    return err
}

func (d *ExposedTxDriver) Release(name string) error {
	_, err := d.Driver.ExecContext(context.Background(), "RELEASE SAVEPOINT " + name)
    return err
}

// HijackTx returns a new transaction driver with the provided options.
// The returned transaction can later be used to instanciate new clients.
func (c *Client) HijackTx(ctx context.Context, opts *sql.TxOptions) (context.Context, *entutils.RawEntConfig, *ExposedTxDriver, error) {
	if _, ok := c.driver.(*txDriver); ok {
		return nil, nil, nil, errors.New("ent: cannot start a transaction within a transaction")
	}
	tx, err := c.driver.(interface {
		BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error)
	}).BeginTx(ctx, opts)
	if err != nil {
		return nil, nil, nil, fmt.Errorf("ent: starting a transaction: %w", err)
	}

	driver := &txDriver{tx: tx, drv: c.driver}

	cfg := c.config
	cfg.driver = &txDriver{tx: tx, drv: c.driver}
	return ctx, &entutils.RawEntConfig{
        Driver: cfg.driver,
        Debug: cfg.debug,
        Log: cfg.log,
    }, &ExposedTxDriver{Driver: driver}, nil
}

// NewTxClientFromConfig creates a new transactional client from a (hijacked) configuration.
func NewTxClientFromRawConfig(ctx context.Context, cfg entutils.RawEntConfig) *Tx {
    config := config{
        driver: cfg.Driver,
        debug:  cfg.Debug,
        log:    cfg.Log,
        hooks: &hooks{},
        inters: &inters{},
    }

    return &Tx{
		ctx:         ctx,
		config:      config,
        // Clients templated from defined schemas
        {{ range $n := $.Nodes }}
            {{ $n.Name }}: New{{ $n.Name }}Client(config),
        {{ end }}
	}
}


{{ end }}