yamori

有給休暇計算を主目的とした簡易勤怠管理システム

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
  100. 100
  101. 101
  102. 102
  103. 103
  104. 104
  105. 105
  106. 106
  107. 107
  108. 108
  109. 109
  110. 110
  111. 111
  112. 112
  113. 113
  114. 114
package sqlite3_js //nolint:golint

import (
	"context"
	"database/sql/driver"
	"fmt"
	"strings"
	"sync"
	"syscall/js"
)

// SqliteJsConn implements driver.Conn.
type SqliteJsConn struct {
	JsDb js.Value // sql.js SQL.Database : https://sql-js.github.io/sql.js/documentation/class/Database.html
	mu   *sync.Mutex
}

// Prepare creates a prepared statement for later queries or executions. Multiple
// queries or executions may be run concurrently from the returned statement. The
// caller must call the statement's Close method when the statement is no longer
// needed.
func (conn *SqliteJsConn) Prepare(query string) (stmt driver.Stmt, err error) {
	defer protect("Prepare", func(e error) { err = e })
	return &SqliteJsStmt{
		c:  conn,
		js: conn.JsDb.Call("prepare", query),
	}, nil
}

// Close returns the connection to the connection pool. All operations after a
// Close will return with ErrConnDone. Close is safe to call concurrently with
// other operations and will block until all other operations finish. It may be
// useful to first cancel any used context and then call close directly after.
func (conn SqliteJsConn) Close() error {
	// TODO
	return nil
}

func (conn *SqliteJsConn) Exec(query string, args []driver.Value) (result driver.Result, err error) {
	defer protect("Exec", func(e error) { err = e })
	query = strings.TrimRight(query, ";")
	if strings.Contains(query, ";") {
		if len(args) != 0 {
			return nil, fmt.Errorf("cannot exec multiple statements with placeholders, query: %s nargs=%d", query, len(args))
		}
		jsVal, err := jsTryCatch(func() js.Value {
			return conn.JsDb.Call("exec", query)
		})
		if err != nil {
			return nil, err
		}
		return &SqliteJsResult{
			js:      jsVal,
			changes: 0,
			id:      0,
		}, nil
	}

	list := make([]namedValue, len(args))
	for i, v := range args {
		list[i] = namedValue{
			Ordinal: i + 1,
			Value:   v,
		}
	}
	return conn.exec(context.Background(), query, list)
}

func (conn *SqliteJsConn) exec(ctx context.Context, query string, args []namedValue) (driver.Result, error) {
	// FIXME: we removed tbe ability to handle 'tails' - is this a problem?
	s, err := conn.Prepare(query)
	if err != nil {
		return nil, err
	}
	var res driver.Result
	res, err = s.(*SqliteJsStmt).exec(ctx, args)
	s.Close()
	return res, err
}

// Transactions

// Begin starts a transaction. The default isolation level is dependent on the driver.
func (conn *SqliteJsConn) Begin() (driver.Tx, error) {
	return conn.begin(context.Background())
}

// BeginTx starts and returns a new transaction.
// If the context is canceled by the user the sql package will
// call Tx.Rollback before discarding and closing the connection.
//
// This must check opts.Isolation to determine if there is a set
// isolation level. If the driver does not support a non-default
// level and one is set or if there is a non-default isolation level
// that is not supported, an error must be returned.
//
// This must also check opts.ReadOnly to determine if the read-only
// value is true to either set the read-only transaction property if supported
// or return an error if it is not supported.
func (conn *SqliteJsConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
	return conn.begin(ctx)
}

func (conn *SqliteJsConn) begin(ctx context.Context) (driver.Tx, error) { //nolint:unparam
	/*
		if conn.disableTxns {
			fmt.Println("Ignoring BEGIN, txns disabled")
			return &SqliteJsTx{c: conn}, nil
		}
		if _, err := conn.exec(ctx, "BEGIN", nil); err != nil {
			return nil, err
		} */
	return &SqliteJsTx{c: conn}, nil
}