| 48 | } |
| 49 | |
| 50 | func (m *ManagedClient) CreateDatabase(ctx context.Context, req *CreateDatabaseRequest) (*CreateDatabaseResponse, error) { |
| 51 | hash := dbid(req.Migrations) |
| 52 | prefix := req.Prefix |
| 53 | if prefix == "" { |
| 54 | prefix = "sqlc_managed" |
| 55 | } |
| 56 | name := fmt.Sprintf("%s_%s", prefix, hash) |
| 57 | |
| 58 | engine := config.Engine(req.Engine) |
| 59 | switch engine { |
| 60 | case config.EngineMySQL: |
| 61 | // pass |
| 62 | case config.EnginePostgreSQL: |
| 63 | // pass |
| 64 | default: |
| 65 | return nil, fmt.Errorf("unsupported engine: %s", engine) |
| 66 | } |
| 67 | |
| 68 | var base string |
| 69 | for _, server := range m.servers { |
| 70 | if server.Engine == engine { |
| 71 | base = server.URI |
| 72 | break |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | if strings.TrimSpace(base) == "" { |
| 77 | return nil, fmt.Errorf("no PostgreSQL database server found") |
| 78 | } |
| 79 | |
| 80 | serverUri := m.replacer.Replace(base) |
| 81 | pool, err := m.cache.Open(ctx, serverUri) |
| 82 | if err != nil { |
| 83 | return nil, err |
| 84 | } |
| 85 | |
| 86 | uri, err := url.Parse(serverUri) |
| 87 | if err != nil { |
| 88 | return nil, err |
| 89 | } |
| 90 | uri.Path = "/" + name |
| 91 | |
| 92 | key := uri.String() |
| 93 | _, err, _ = flight.Do(key, func() (interface{}, error) { |
| 94 | // TODO: Use a parameterized query |
| 95 | row := pool.QueryRow(ctx, |
| 96 | fmt.Sprintf(`SELECT datname FROM pg_database WHERE datname = '%s'`, name)) |
| 97 | |
| 98 | var datname string |
| 99 | if err := row.Scan(&datname); err == nil { |
| 100 | return nil, nil |
| 101 | } |
| 102 | |
| 103 | if _, err := pool.Exec(ctx, fmt.Sprintf(`CREATE DATABASE "%s"`, name)); err != nil { |
| 104 | return nil, err |
| 105 | } |
| 106 | |
| 107 | conn, err := pgx.Connect(ctx, uri.String()) |