You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sql_postgres_with_schema.go 1.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package db
  4. import (
  5. "database/sql"
  6. "database/sql/driver"
  7. "sync"
  8. "code.gitea.io/gitea/modules/setting"
  9. "github.com/lib/pq"
  10. "xorm.io/xorm/dialects"
  11. )
  12. var registerOnce sync.Once
  13. func registerPostgresSchemaDriver() {
  14. registerOnce.Do(func() {
  15. sql.Register("postgresschema", &postgresSchemaDriver{})
  16. dialects.RegisterDriver("postgresschema", dialects.QueryDriver("postgres"))
  17. })
  18. }
  19. type postgresSchemaDriver struct {
  20. pq.Driver
  21. }
  22. // Open opens a new connection to the database. name is a connection string.
  23. // This function opens the postgres connection in the default manner but immediately
  24. // runs set_config to set the search_path appropriately
  25. func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
  26. conn, err := d.Driver.Open(name)
  27. if err != nil {
  28. return conn, err
  29. }
  30. schemaValue, _ := driver.String.ConvertValue(setting.Database.Schema)
  31. // golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here
  32. // and in any case pq does not implement it
  33. if execer, ok := conn.(driver.Execer); ok { //nolint
  34. _, err := execer.Exec(`SELECT set_config(
  35. 'search_path',
  36. $1 || ',' || current_setting('search_path'),
  37. false)`, []driver.Value{schemaValue})
  38. if err != nil {
  39. _ = conn.Close()
  40. return nil, err
  41. }
  42. return conn, nil
  43. }
  44. stmt, err := conn.Prepare(`SELECT set_config(
  45. 'search_path',
  46. $1 || ',' || current_setting('search_path'),
  47. false)`)
  48. if err != nil {
  49. _ = conn.Close()
  50. return nil, err
  51. }
  52. defer stmt.Close()
  53. // driver.String.ConvertValue will never return err for string
  54. // golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here
  55. _, err = stmt.Exec([]driver.Value{schemaValue}) //nolint
  56. if err != nil {
  57. _ = conn.Close()
  58. return nil, err
  59. }
  60. return conn, nil
  61. }