1// Copyright 2012 James Cooper. All rights reserved.
2// Use of this source code is governed by a MIT-style
3// license that can be found in the LICENSE file.
4
5// Package gorp provides a simple way to marshal Go structs to and from
6// SQL databases.  It uses the database/sql package, and should work with any
7// compliant database/sql driver.
8//
9// Source code and project home:
10// https://github.com/go-gorp/gorp
11
12package gorp
13
14import "reflect"
15
16// The Dialect interface encapsulates behaviors that differ across
17// SQL databases.  At present the Dialect is only used by CreateTables()
18// but this could change in the future
19type Dialect interface {
20
21	// dialect name
22	Name() string
23
24	// adds a suffix to any query, usually ";"
25	QuerySuffix() string
26
27	// ToSqlType returns the SQL column type to use when creating a
28	// table of the given Go Type.  maxsize can be used to switch based on
29	// size.  For example, in MySQL []byte could map to BLOB, MEDIUMBLOB,
30	// or LONGBLOB depending on the maxsize
31	ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string
32
33	// string to append to primary key column definitions
34	AutoIncrStr() string
35
36	// string to bind autoincrement columns to. Empty string will
37	// remove reference to those columns in the INSERT statement.
38	AutoIncrBindValue() string
39
40	AutoIncrInsertSuffix(col *ColumnMap) string
41
42	// string to append to "create table" statement for vendor specific
43	// table attributes
44	CreateTableSuffix() string
45
46	// string to append to "create index" statement
47	CreateIndexSuffix() string
48
49	// string to append to "drop index" statement
50	DropIndexSuffix() string
51
52	// string to truncate tables
53	TruncateClause() string
54
55	// bind variable string to use when forming SQL statements
56	// in many dbs it is "?", but Postgres appears to use $1
57	//
58	// i is a zero based index of the bind variable in this statement
59	//
60	BindVar(i int) string
61
62	// Handles quoting of a field name to ensure that it doesn't raise any
63	// SQL parsing exceptions by using a reserved word as a field name.
64	QuoteField(field string) string
65
66	// Handles building up of a schema.database string that is compatible with
67	// the given dialect
68	//
69	// schema - The schema that <table> lives in
70	// table - The table name
71	QuotedTableForQuery(schema string, table string) string
72
73	// Existance clause for table creation / deletion
74	IfSchemaNotExists(command, schema string) string
75	IfTableExists(command, schema, table string) string
76	IfTableNotExists(command, schema, table string) string
77}
78
79// IntegerAutoIncrInserter is implemented by dialects that can perform
80// inserts with automatically incremented integer primary keys.  If
81// the dialect can handle automatic assignment of more than just
82// integers, see TargetedAutoIncrInserter.
83type IntegerAutoIncrInserter interface {
84	InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error)
85}
86
87// TargetedAutoIncrInserter is implemented by dialects that can
88// perform automatic assignment of any primary key type (i.e. strings
89// for uuids, integers for serials, etc).
90type TargetedAutoIncrInserter interface {
91	// InsertAutoIncrToTarget runs an insert operation and assigns the
92	// automatically generated primary key directly to the passed in
93	// target.  The target should be a pointer to the primary key
94	// field of the value being inserted.
95	InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error
96}
97
98// TargetQueryInserter is implemented by dialects that can perform
99// assignment of integer primary key type by executing a query
100// like "select sequence.currval from dual".
101type TargetQueryInserter interface {
102	// TargetQueryInserter runs an insert operation and assigns the
103	// automatically generated primary key retrived by the query
104	// extracted from the GeneratedIdQuery field of the id column.
105	InsertQueryToTarget(exec SqlExecutor, insertSql, idSql string, target interface{}, params ...interface{}) error
106}
107
108func standardInsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) {
109	res, err := exec.Exec(insertSql, params...)
110	if err != nil {
111		return 0, err
112	}
113	return res.LastInsertId()
114}
115