2013-07-30 12:32:38 +00:00
package orm
2013-08-10 16:15:26 +00:00
import (
2013-08-11 14:27:45 +00:00
"fmt"
2013-08-10 16:15:26 +00:00
"strconv"
)
2014-01-17 09:25:17 +00:00
// postgresql operators.
2013-08-10 16:15:26 +00:00
var postgresOperators = map [ string ] string {
"exact" : "= ?" ,
"iexact" : "= UPPER(?)" ,
"contains" : "LIKE ?" ,
"icontains" : "LIKE UPPER(?)" ,
"gt" : "> ?" ,
"gte" : ">= ?" ,
"lt" : "< ?" ,
"lte" : "<= ?" ,
"startswith" : "LIKE ?" ,
"endswith" : "LIKE ?" ,
"istartswith" : "LIKE UPPER(?)" ,
"iendswith" : "LIKE UPPER(?)" ,
}
2014-01-17 09:25:17 +00:00
// postgresql column field types.
2013-08-19 14:37:39 +00:00
var postgresTypes = map [ string ] string {
"auto" : "serial NOT NULL PRIMARY KEY" ,
"pk" : "NOT NULL PRIMARY KEY" ,
"bool" : "bool" ,
"string" : "varchar(%d)" ,
"string-text" : "text" ,
"time.Time-date" : "date" ,
"time.Time" : "timestamp with time zone" ,
"int8" : ` smallint CHECK("%COL%" >= -127 AND "%COL%" <= 128) ` ,
"int16" : "smallint" ,
"int32" : "integer" ,
"int64" : "bigint" ,
"uint8" : ` smallint CHECK("%COL%" >= 0 AND "%COL%" <= 255) ` ,
"uint16" : ` integer CHECK("%COL%" >= 0) ` ,
"uint32" : ` bigint CHECK("%COL%" >= 0) ` ,
"uint64" : ` bigint CHECK("%COL%" >= 0) ` ,
"float64" : "double precision" ,
"float64-decimal" : "numeric(%d, %d)" ,
}
2014-01-17 09:25:17 +00:00
// postgresql dbBaser.
2013-07-30 12:32:38 +00:00
type dbBasePostgres struct {
dbBase
}
2013-08-10 16:15:26 +00:00
var _ dbBaser = new ( dbBasePostgres )
2014-01-17 09:25:17 +00:00
// get postgresql operator.
2013-08-10 16:15:26 +00:00
func ( d * dbBasePostgres ) OperatorSql ( operator string ) string {
return postgresOperators [ operator ]
}
2014-01-17 09:25:17 +00:00
// generate functioned sql string, such as contains(text).
2013-08-13 09:16:12 +00:00
func ( d * dbBasePostgres ) GenerateOperatorLeftCol ( fi * fieldInfo , operator string , leftCol * string ) {
2013-08-11 14:27:45 +00:00
switch operator {
case "contains" , "startswith" , "endswith" :
* leftCol = fmt . Sprintf ( "%s::text" , * leftCol )
case "iexact" , "icontains" , "istartswith" , "iendswith" :
* leftCol = fmt . Sprintf ( "UPPER(%s::text)" , * leftCol )
}
}
2014-01-17 09:25:17 +00:00
// postgresql unsupports updating joined record.
2013-08-11 14:27:45 +00:00
func ( d * dbBasePostgres ) SupportUpdateJoin ( ) bool {
return false
}
func ( d * dbBasePostgres ) MaxLimit ( ) uint64 {
return 0
}
2014-01-17 09:25:17 +00:00
// postgresql quote is ".
2013-08-10 16:15:26 +00:00
func ( d * dbBasePostgres ) TableQuote ( ) string {
return ` " `
}
2014-01-17 09:25:17 +00:00
// postgresql value placeholder is $n.
// replace default ? to $n.
2013-08-10 16:15:26 +00:00
func ( d * dbBasePostgres ) ReplaceMarks ( query * string ) {
q := * query
num := 0
for _ , c := range q {
if c == '?' {
num += 1
}
}
if num == 0 {
return
}
data := make ( [ ] byte , 0 , len ( q ) + num )
num = 1
for i := 0 ; i < len ( q ) ; i ++ {
c := q [ i ]
if c == '?' {
data = append ( data , '$' )
data = append ( data , [ ] byte ( strconv . Itoa ( num ) ) ... )
num += 1
} else {
data = append ( data , c )
}
}
* query = string ( data )
}
2014-01-17 09:25:17 +00:00
// make returning sql support for postgresql.
2013-08-11 14:27:45 +00:00
func ( d * dbBasePostgres ) HasReturningID ( mi * modelInfo , query * string ) ( has bool ) {
if mi . fields . pk . auto {
if query != nil {
* query = fmt . Sprintf ( ` %s RETURNING "%s" ` , * query , mi . fields . pk . column )
}
has = true
}
return
}
2013-08-10 16:15:26 +00:00
2014-01-17 09:25:17 +00:00
// show table sql for postgresql.
2013-08-27 04:33:27 +00:00
func ( d * dbBasePostgres ) ShowTablesQuery ( ) string {
return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')"
}
2014-01-17 09:25:17 +00:00
// show table columns sql for postgresql.
2013-08-27 04:33:27 +00:00
func ( d * dbBasePostgres ) ShowColumnsQuery ( table string ) string {
return fmt . Sprintf ( "SELECT column_name, data_type, is_nullable FROM information_schema.columns where table_schema NOT IN ('pg_catalog', 'information_schema') and table_name = '%s'" , table )
}
2014-01-17 09:25:17 +00:00
// get column types of postgresql.
2013-08-19 14:37:39 +00:00
func ( d * dbBasePostgres ) DbTypes ( ) map [ string ] string {
return postgresTypes
}
2014-01-17 09:25:17 +00:00
// check index exist in postgresql.
2013-08-27 04:33:27 +00:00
func ( d * dbBasePostgres ) IndexExists ( db dbQuerier , table string , name string ) bool {
query := fmt . Sprintf ( "SELECT COUNT(*) FROM pg_indexes WHERE tablename = '%s' AND indexname = '%s'" , table , name )
row := db . QueryRow ( query )
var cnt int
row . Scan ( & cnt )
return cnt > 0
}
2014-01-17 09:25:17 +00:00
// create new postgresql dbBaser.
2013-07-30 12:32:38 +00:00
func newdbBasePostgres ( ) dbBaser {
b := new ( dbBasePostgres )
b . ins = b
return b
}