database.*Postgresql.DSN   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 0
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
package database
2
3
import (
4
	"fmt"
5
	"strings"
6
7
	"github.com/fraenky8/tables-to-go/pkg/settings"
8
9
	// postgres database driver
10
	_ "github.com/lib/pq"
11
)
12
13
// Postgresql implemenmts the Database interface with help of generalDatabase
14
type Postgresql struct {
15
	*GeneralDatabase
16
17
	defaultUserName string
18
}
19
20
// NewPostgresql creates a new Postgresql database
21
func NewPostgresql(s *settings.Settings) *Postgresql {
22 1
	return &Postgresql{
23
		GeneralDatabase: &GeneralDatabase{
24
			Settings: s,
25
			driver:   dbTypeToDriverMap[s.DbType],
26
		},
27
		defaultUserName: "postgres",
28
	}
29
}
30
31
// Connect connects to the database by the given data source name (dsn) of the concrete database
32
func (pg *Postgresql) Connect() error {
33
	return pg.GeneralDatabase.Connect(pg.DSN())
34
}
35
36
// DSN creates the DSN String to connect to this database
37
func (pg *Postgresql) DSN() string {
38 1
	user := pg.defaultUserName
39 1
	if pg.Settings.User != "" {
40 1
		user = pg.Settings.User
41
	}
42 1
	return fmt.Sprintf("host=%v port=%v user=%v dbname=%v password=%v sslmode=disable",
43
		pg.Settings.Host, pg.Settings.Port, user, pg.Settings.DbName, pg.Settings.Pswd)
44
}
45
46
// GetDriverImportLibrary returns the golang sql driver specific fot the MySQL database
47
func (pg *Postgresql) GetDriverImportLibrary() string {
48
	return "pg \"github.com/lib/pq\""
49
}
50
51
// GetTables gets all tables for a given schema by name
52
func (pg *Postgresql) GetTables() (tables []*Table, err error) {
53
54
	err = pg.Select(&tables, `
55
		SELECT table_name
56
		FROM information_schema.tables
57
		WHERE table_type = 'BASE TABLE'
58
		AND table_schema = $1
59
		ORDER BY table_name
60
	`, pg.Schema)
61
62
	if pg.Verbose {
63
		if err != nil {
64
			fmt.Println("> Error at GetTables()")
65
			fmt.Printf("> schema: %q\r\n", pg.Schema)
66
		}
67
	}
68
69
	return tables, err
70
}
71
72
// PrepareGetColumnsOfTableStmt prepares the statement for retrieving the columns of a specific table for a given database
73
func (pg *Postgresql) PrepareGetColumnsOfTableStmt() (err error) {
74
75
	pg.GetColumnsOfTableStmt, err = pg.Preparex(`
76
		SELECT
77
			ic.ordinal_position,
78
			ic.column_name,
79
			ic.data_type,
80
			ic.column_default,
81
			ic.is_nullable,
82
			ic.character_maximum_length,
83
			ic.numeric_precision,
84
			itc.constraint_name,
85
			itc.constraint_type
86
		FROM information_schema.columns AS ic
87
			LEFT JOIN information_schema.key_column_usage AS ikcu ON ic.table_name = ikcu.table_name
88
			AND ic.table_schema = ikcu.table_schema
89
			AND ic.column_name = ikcu.column_name
90
			LEFT JOIN information_schema.table_constraints AS itc ON ic.table_name = itc.table_name
91
			AND ic.table_schema = itc.table_schema
92
			AND ikcu.constraint_name = itc.constraint_name
93
		WHERE ic.table_name = $1
94
		AND ic.table_schema = $2
95
		ORDER BY ic.ordinal_position
96
	`)
97
98
	return err
99
}
100
101
// GetColumnsOfTable executes the statement for retrieving the columns of a specific table in a given schema
102
func (pg *Postgresql) GetColumnsOfTable(table *Table) (err error) {
103
104
	err = pg.GetColumnsOfTableStmt.Select(&table.Columns, table.Name, pg.Schema)
105
106
	if pg.Verbose {
107
		if err != nil {
108
			fmt.Printf("> Error at GetColumnsOfTable(%v)\r\n", table.Name)
109
			fmt.Printf("> schema: %q\r\n", pg.Schema)
110
		}
111
	}
112
113
	return err
114
}
115
116
// IsPrimaryKey checks if column belongs to primary key
117
func (pg *Postgresql) IsPrimaryKey(column Column) bool {
118
	return strings.Contains(column.ConstraintType.String, "PRIMARY KEY")
119
}
120
121
// IsAutoIncrement checks if column is a serial column
122
func (pg *Postgresql) IsAutoIncrement(column Column) bool {
123
	return strings.Contains(column.DefaultValue.String, "nextval")
124
}
125
126
// GetStringDatatypes returns the string datatypes for the postgre database
127
func (pg *Postgresql) GetStringDatatypes() []string {
128
	return []string{
129
		"character varying",
130
		"varchar",
131
		"character",
132
		"char",
133
	}
134
}
135
136
// IsString returns true if colum is of type string for the postgre database
137
func (pg *Postgresql) IsString(column Column) bool {
138
	return pg.IsStringInSlice(column.DataType, pg.GetStringDatatypes())
139
}
140
141
// GetTextDatatypes returns the text datatypes for the postgre database
142
func (pg *Postgresql) GetTextDatatypes() []string {
143
	return []string{
144
		"text",
145
	}
146
}
147
148
// IsText returns true if colum is of type text for the postgre database
149
func (pg *Postgresql) IsText(column Column) bool {
150
	return pg.IsStringInSlice(column.DataType, pg.GetTextDatatypes())
151
}
152
153
// GetIntegerDatatypes returns the integer datatypes for the postgre database
154
func (pg *Postgresql) GetIntegerDatatypes() []string {
155
	return []string{
156
		"smallint",
157
		"integer",
158
		"bigint",
159
		"smallserial",
160
		"serial",
161
		"bigserial",
162
	}
163
}
164
165
// IsInteger returns true if colum is of type integer for the postgre database
166
func (pg *Postgresql) IsInteger(column Column) bool {
167
	return pg.IsStringInSlice(column.DataType, pg.GetIntegerDatatypes())
168
}
169
170
// GetFloatDatatypes returns the float datatypes for the postgre database
171
func (pg *Postgresql) GetFloatDatatypes() []string {
172
	return []string{
173
		"numeric",
174
		"decimal",
175
		"real",
176
		"double precision",
177
	}
178
}
179
180
// IsFloat returns true if colum is of type float for the postgre database
181
func (pg *Postgresql) IsFloat(column Column) bool {
182
	return pg.IsStringInSlice(column.DataType, pg.GetFloatDatatypes())
183
}
184
185
// GetTemporalDatatypes returns the temporal datatypes for the postgre database
186
func (pg *Postgresql) GetTemporalDatatypes() []string {
187
	return []string{
188
		"time",
189
		"timestamp",
190
		"time with time zone",
191
		"timestamp with time zone",
192
		"time without time zone",
193
		"timestamp without time zone",
194
		"date",
195
	}
196
}
197
198
// IsTemporal returns true if colum is of type temporal for the postgre database
199
func (pg *Postgresql) IsTemporal(column Column) bool {
200
	return pg.IsStringInSlice(column.DataType, pg.GetTemporalDatatypes())
201
}
202
203
// GetTemporalDriverDataType returns the time data type specific for the postgre database
204
func (pg *Postgresql) GetTemporalDriverDataType() string {
205
	return "pg.NullTime"
206
}
207