2014-04-25 03:20:23 +04:00
package gorm
2013-11-14 14:59:11 +04:00
import (
2014-06-08 03:15:58 +04:00
"database/sql"
"database/sql/driver"
2013-11-14 14:59:11 +04:00
"fmt"
2014-12-08 14:03:42 +03:00
"reflect"
2015-02-17 17:55:14 +03:00
"time"
2015-01-14 02:59:21 +03:00
"github.com/lib/pq/hstore"
2013-11-14 14:59:11 +04:00
)
type postgres struct {
}
2013-11-16 16:47:25 +04:00
func ( s * postgres ) BinVar ( i int ) string {
return fmt . Sprintf ( "$%v" , i )
2013-11-14 14:59:11 +04:00
}
func ( s * postgres ) SupportLastInsertId ( ) bool {
return false
}
2014-09-16 00:03:14 +04:00
func ( s * postgres ) HasTop ( ) bool {
2014-09-16 19:32:35 +04:00
return false
2014-09-16 00:03:14 +04:00
}
2015-02-17 03:34:01 +03:00
func ( s * postgres ) SqlTag ( value reflect . Value , size int ) string {
2014-03-16 05:28:43 +04:00
switch value . Kind ( ) {
case reflect . Bool :
2013-11-14 14:59:11 +04:00
return "boolean"
2014-03-16 05:28:43 +04:00
case reflect . Int , reflect . Int8 , reflect . Int16 , reflect . Int32 , reflect . Uint , reflect . Uint8 , reflect . Uint16 , reflect . Uint32 , reflect . Uintptr :
2013-11-14 14:59:11 +04:00
return "integer"
2014-03-16 05:28:43 +04:00
case reflect . Int64 , reflect . Uint64 :
2013-11-14 14:59:11 +04:00
return "bigint"
2014-03-16 05:28:43 +04:00
case reflect . Float32 , reflect . Float64 :
2013-12-03 04:23:26 +04:00
return "numeric"
2014-03-16 05:28:43 +04:00
case reflect . String :
2013-11-14 14:59:11 +04:00
if size > 0 && size < 65532 {
return fmt . Sprintf ( "varchar(%d)" , size )
2014-03-16 05:28:43 +04:00
}
return "text"
case reflect . Struct :
2015-02-17 17:55:14 +03:00
if _ , ok := value . Interface ( ) . ( time . Time ) ; ok {
2014-03-16 05:28:43 +04:00
return "timestamp with time zone"
2013-11-14 14:59:11 +04:00
}
2014-06-08 03:15:58 +04:00
case reflect . Map :
if value . Type ( ) == hstoreType {
return "hstore"
}
2013-11-14 14:59:11 +04:00
default :
2014-03-16 05:28:43 +04:00
if _ , ok := value . Interface ( ) . ( [ ] byte ) ; ok {
return "bytea"
}
2013-11-14 14:59:11 +04:00
}
2014-03-16 05:28:43 +04:00
panic ( fmt . Sprintf ( "invalid sql type %s (%s) for postgres" , value . Type ( ) . Name ( ) , value . Kind ( ) . String ( ) ) )
2013-11-14 14:59:11 +04:00
}
2014-03-16 05:28:43 +04:00
func ( s * postgres ) PrimaryKeyTag ( value reflect . Value , size int ) string {
switch value . Kind ( ) {
case reflect . Int , reflect . Int8 , reflect . Int16 , reflect . Int32 , reflect . Uint , reflect . Uint8 , reflect . Uint16 , reflect . Uint32 , reflect . Uintptr :
2013-12-06 04:19:40 +04:00
return "serial PRIMARY KEY"
2014-03-16 05:28:43 +04:00
case reflect . Int64 , reflect . Uint64 :
2013-12-06 04:19:40 +04:00
return "bigserial PRIMARY KEY"
2013-11-14 14:59:11 +04:00
default :
panic ( "Invalid primary key type" )
}
}
2014-12-08 14:03:42 +03:00
func ( s * postgres ) ReturningStr ( tableName , key string ) string {
2015-01-14 02:59:21 +03:00
return fmt . Sprintf ( "RETURNING %v.%v" , s . Quote ( tableName ) , key )
2013-11-14 14:59:11 +04:00
}
2013-11-30 10:52:01 +04:00
2014-07-30 10:18:15 +04:00
func ( s * postgres ) SelectFromDummyTable ( ) string {
return ""
}
2014-04-25 03:20:23 +04:00
func ( s * postgres ) Quote ( key string ) string {
2013-11-30 10:52:01 +04:00
return fmt . Sprintf ( "\"%s\"" , key )
}
2014-04-25 05:08:48 +04:00
func ( s * postgres ) HasTable ( scope * Scope , tableName string ) bool {
var count int
newScope := scope . New ( nil )
2014-08-29 02:22:59 +04:00
newScope . Raw ( fmt . Sprintf ( "SELECT count(*) FROM INFORMATION_SCHEMA.tables where table_name = %v and table_type = 'BASE TABLE'" , newScope . AddToVars ( tableName ) ) )
2014-04-25 05:08:48 +04:00
newScope . DB ( ) . QueryRow ( newScope . Sql , newScope . SqlVars ... ) . Scan ( & count )
return count > 0
}
func ( s * postgres ) HasColumn ( scope * Scope , tableName string , columnName string ) bool {
var count int
newScope := scope . New ( nil )
newScope . Raw ( fmt . Sprintf ( "SELECT count(*) FROM information_schema.columns WHERE table_name = %v AND column_name = %v" ,
newScope . AddToVars ( tableName ) ,
newScope . AddToVars ( columnName ) ,
) )
newScope . DB ( ) . QueryRow ( newScope . Sql , newScope . SqlVars ... ) . Scan ( & count )
return count > 0
}
2014-06-08 03:15:58 +04:00
2014-07-29 08:02:03 +04:00
func ( s * postgres ) RemoveIndex ( scope * Scope , indexName string ) {
2015-01-14 02:27:35 +03:00
scope . Raw ( fmt . Sprintf ( "DROP INDEX %v" , s . Quote ( indexName ) ) ) . Exec ( )
2014-07-29 08:02:03 +04:00
}
2014-06-08 03:15:58 +04:00
var hstoreType = reflect . TypeOf ( Hstore { } )
type Hstore map [ string ] * string
func ( h Hstore ) Value ( ) ( driver . Value , error ) {
hstore := hstore . Hstore { Map : map [ string ] sql . NullString { } }
if len ( h ) == 0 {
return nil , nil
}
for key , value := range h {
2014-07-10 18:15:39 +04:00
hstore . Map [ key ] = sql . NullString { String : * value , Valid : true }
2014-06-08 03:15:58 +04:00
}
return hstore . Value ( )
}
func ( h * Hstore ) Scan ( value interface { } ) error {
hstore := hstore . Hstore { }
if err := hstore . Scan ( value ) ; err != nil {
return err
}
if len ( hstore . Map ) == 0 {
return nil
}
* h = Hstore { }
for k := range hstore . Map {
if hstore . Map [ k ] . Valid {
s := hstore . Map [ k ] . String
( * h ) [ k ] = & s
} else {
( * h ) [ k ] = nil
}
}
return nil
}