// Copyright 2026 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package spanner provides access to the Cloud Spanner API.
//
// This package is DEPRECATED. Use package cloud.google.com/go/spanner instead.
//
// For product documentation, see: https://cloud.google.com/spanner/
//
// # Library status
//
// These client libraries are officially supported by Google. However, this
// library is considered complete and is in maintenance mode. This means
// that we will address critical bugs and security issues but will not add
// any new features.
//
// When possible, we recommend using our newer
// [Cloud Client Libraries for Go](https://pkg.go.dev/cloud.google.com/go)
// that are still actively being worked and iterated on.
//
// # Creating a client
//
// Usage example:
//
//	import "google.golang.org/api/spanner/v1"
//	...
//	ctx := context.Background()
//	spannerService, err := spanner.NewService(ctx)
//
// In this example, Google Application Default Credentials are used for
// authentication. For information on how to create and obtain Application
// Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
//
// # Other authentication options
//
// By default, all available scopes (see "Constants") are used to authenticate.
// To restrict scopes, use [google.golang.org/api/option.WithScopes]:
//
//	spannerService, err := spanner.NewService(ctx, option.WithScopes(spanner.SpannerDataScope))
//
// To use an API key for authentication (note: some APIs do not support API
// keys), use [google.golang.org/api/option.WithAPIKey]:
//
//	spannerService, err := spanner.NewService(ctx, option.WithAPIKey("AIza..."))
//
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth
// flow, use [google.golang.org/api/option.WithTokenSource]:
//
//	config := &oauth2.Config{...}
//	// ...
//	token, err := config.Exchange(ctx, ...)
//	spannerService, err := spanner.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See [google.golang.org/api/option.ClientOption] for details on options.
package spanner // import "google.golang.org/api/spanner/v1"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/googleapis/gax-go/v2/internallog"
	googleapi "google.golang.org/api/googleapi"
	internal "google.golang.org/api/internal"
	gensupport "google.golang.org/api/internal/gensupport"
	option "google.golang.org/api/option"
	internaloption "google.golang.org/api/option/internaloption"
	htransport "google.golang.org/api/transport/http"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled
var _ = internaloption.WithDefaultEndpoint
var _ = internal.Version
var _ = internallog.New

const apiId = "spanner:v1"
const apiName = "spanner"
const apiVersion = "v1"
const basePath = "https://spanner.googleapis.com/"
const basePathTemplate = "https://spanner.UNIVERSE_DOMAIN/"
const mtlsBasePath = "https://spanner.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// See, edit, configure, and delete your Google Cloud data and see the email
	// address for your Google Account.
	CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"

	// Administer your Spanner databases
	SpannerAdminScope = "https://www.googleapis.com/auth/spanner.admin"

	// See, edit, configure, and delete your Google Cloud Spanner data and see the
	// email address for your Google Account
	SpannerDataScope = "https://www.googleapis.com/auth/spanner.data"
)

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	scopesOption := internaloption.WithDefaultScopes(
		"https://www.googleapis.com/auth/cloud-platform",
		"https://www.googleapis.com/auth/spanner.admin",
		"https://www.googleapis.com/auth/spanner.data",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	opts = append(opts, internaloption.WithDefaultEndpointTemplate(basePathTemplate))
	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
	opts = append(opts, internaloption.EnableNewAuthLibrary())
	client, endpoint, err := htransport.NewClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	s := &Service{client: client, BasePath: basePath, logger: internaloption.GetLogger(opts)}
	s.Projects = NewProjectsService(s)
	s.Scans = NewScansService(s)
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new Service. It uses the provided http.Client for requests.
//
// Deprecated: please use NewService instead.
// To provide a custom HTTP client, use option.WithHTTPClient.
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	return NewService(context.TODO(), option.WithHTTPClient(client))
}

type Service struct {
	client    *http.Client
	logger    *slog.Logger
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment

	Projects *ProjectsService

	Scans *ScansService
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

func NewProjectsService(s *Service) *ProjectsService {
	rs := &ProjectsService{s: s}
	rs.InstanceConfigOperations = NewProjectsInstanceConfigOperationsService(s)
	rs.InstanceConfigs = NewProjectsInstanceConfigsService(s)
	rs.Instances = NewProjectsInstancesService(s)
	return rs
}

type ProjectsService struct {
	s *Service

	InstanceConfigOperations *ProjectsInstanceConfigOperationsService

	InstanceConfigs *ProjectsInstanceConfigsService

	Instances *ProjectsInstancesService
}

func NewProjectsInstanceConfigOperationsService(s *Service) *ProjectsInstanceConfigOperationsService {
	rs := &ProjectsInstanceConfigOperationsService{s: s}
	return rs
}

type ProjectsInstanceConfigOperationsService struct {
	s *Service
}

func NewProjectsInstanceConfigsService(s *Service) *ProjectsInstanceConfigsService {
	rs := &ProjectsInstanceConfigsService{s: s}
	rs.Operations = NewProjectsInstanceConfigsOperationsService(s)
	rs.SsdCaches = NewProjectsInstanceConfigsSsdCachesService(s)
	return rs
}

type ProjectsInstanceConfigsService struct {
	s *Service

	Operations *ProjectsInstanceConfigsOperationsService

	SsdCaches *ProjectsInstanceConfigsSsdCachesService
}

func NewProjectsInstanceConfigsOperationsService(s *Service) *ProjectsInstanceConfigsOperationsService {
	rs := &ProjectsInstanceConfigsOperationsService{s: s}
	return rs
}

type ProjectsInstanceConfigsOperationsService struct {
	s *Service
}

func NewProjectsInstanceConfigsSsdCachesService(s *Service) *ProjectsInstanceConfigsSsdCachesService {
	rs := &ProjectsInstanceConfigsSsdCachesService{s: s}
	rs.Operations = NewProjectsInstanceConfigsSsdCachesOperationsService(s)
	return rs
}

type ProjectsInstanceConfigsSsdCachesService struct {
	s *Service

	Operations *ProjectsInstanceConfigsSsdCachesOperationsService
}

func NewProjectsInstanceConfigsSsdCachesOperationsService(s *Service) *ProjectsInstanceConfigsSsdCachesOperationsService {
	rs := &ProjectsInstanceConfigsSsdCachesOperationsService{s: s}
	return rs
}

type ProjectsInstanceConfigsSsdCachesOperationsService struct {
	s *Service
}

func NewProjectsInstancesService(s *Service) *ProjectsInstancesService {
	rs := &ProjectsInstancesService{s: s}
	rs.BackupOperations = NewProjectsInstancesBackupOperationsService(s)
	rs.Backups = NewProjectsInstancesBackupsService(s)
	rs.DatabaseOperations = NewProjectsInstancesDatabaseOperationsService(s)
	rs.Databases = NewProjectsInstancesDatabasesService(s)
	rs.InstancePartitionOperations = NewProjectsInstancesInstancePartitionOperationsService(s)
	rs.InstancePartitions = NewProjectsInstancesInstancePartitionsService(s)
	rs.Operations = NewProjectsInstancesOperationsService(s)
	return rs
}

type ProjectsInstancesService struct {
	s *Service

	BackupOperations *ProjectsInstancesBackupOperationsService

	Backups *ProjectsInstancesBackupsService

	DatabaseOperations *ProjectsInstancesDatabaseOperationsService

	Databases *ProjectsInstancesDatabasesService

	InstancePartitionOperations *ProjectsInstancesInstancePartitionOperationsService

	InstancePartitions *ProjectsInstancesInstancePartitionsService

	Operations *ProjectsInstancesOperationsService
}

func NewProjectsInstancesBackupOperationsService(s *Service) *ProjectsInstancesBackupOperationsService {
	rs := &ProjectsInstancesBackupOperationsService{s: s}
	return rs
}

type ProjectsInstancesBackupOperationsService struct {
	s *Service
}

func NewProjectsInstancesBackupsService(s *Service) *ProjectsInstancesBackupsService {
	rs := &ProjectsInstancesBackupsService{s: s}
	rs.Operations = NewProjectsInstancesBackupsOperationsService(s)
	return rs
}

type ProjectsInstancesBackupsService struct {
	s *Service

	Operations *ProjectsInstancesBackupsOperationsService
}

func NewProjectsInstancesBackupsOperationsService(s *Service) *ProjectsInstancesBackupsOperationsService {
	rs := &ProjectsInstancesBackupsOperationsService{s: s}
	return rs
}

type ProjectsInstancesBackupsOperationsService struct {
	s *Service
}

func NewProjectsInstancesDatabaseOperationsService(s *Service) *ProjectsInstancesDatabaseOperationsService {
	rs := &ProjectsInstancesDatabaseOperationsService{s: s}
	return rs
}

type ProjectsInstancesDatabaseOperationsService struct {
	s *Service
}

func NewProjectsInstancesDatabasesService(s *Service) *ProjectsInstancesDatabasesService {
	rs := &ProjectsInstancesDatabasesService{s: s}
	rs.BackupSchedules = NewProjectsInstancesDatabasesBackupSchedulesService(s)
	rs.DatabaseRoles = NewProjectsInstancesDatabasesDatabaseRolesService(s)
	rs.Operations = NewProjectsInstancesDatabasesOperationsService(s)
	rs.Sessions = NewProjectsInstancesDatabasesSessionsService(s)
	return rs
}

type ProjectsInstancesDatabasesService struct {
	s *Service

	BackupSchedules *ProjectsInstancesDatabasesBackupSchedulesService

	DatabaseRoles *ProjectsInstancesDatabasesDatabaseRolesService

	Operations *ProjectsInstancesDatabasesOperationsService

	Sessions *ProjectsInstancesDatabasesSessionsService
}

func NewProjectsInstancesDatabasesBackupSchedulesService(s *Service) *ProjectsInstancesDatabasesBackupSchedulesService {
	rs := &ProjectsInstancesDatabasesBackupSchedulesService{s: s}
	return rs
}

type ProjectsInstancesDatabasesBackupSchedulesService struct {
	s *Service
}

func NewProjectsInstancesDatabasesDatabaseRolesService(s *Service) *ProjectsInstancesDatabasesDatabaseRolesService {
	rs := &ProjectsInstancesDatabasesDatabaseRolesService{s: s}
	return rs
}

type ProjectsInstancesDatabasesDatabaseRolesService struct {
	s *Service
}

func NewProjectsInstancesDatabasesOperationsService(s *Service) *ProjectsInstancesDatabasesOperationsService {
	rs := &ProjectsInstancesDatabasesOperationsService{s: s}
	return rs
}

type ProjectsInstancesDatabasesOperationsService struct {
	s *Service
}

func NewProjectsInstancesDatabasesSessionsService(s *Service) *ProjectsInstancesDatabasesSessionsService {
	rs := &ProjectsInstancesDatabasesSessionsService{s: s}
	return rs
}

type ProjectsInstancesDatabasesSessionsService struct {
	s *Service
}

func NewProjectsInstancesInstancePartitionOperationsService(s *Service) *ProjectsInstancesInstancePartitionOperationsService {
	rs := &ProjectsInstancesInstancePartitionOperationsService{s: s}
	return rs
}

type ProjectsInstancesInstancePartitionOperationsService struct {
	s *Service
}

func NewProjectsInstancesInstancePartitionsService(s *Service) *ProjectsInstancesInstancePartitionsService {
	rs := &ProjectsInstancesInstancePartitionsService{s: s}
	rs.Operations = NewProjectsInstancesInstancePartitionsOperationsService(s)
	return rs
}

type ProjectsInstancesInstancePartitionsService struct {
	s *Service

	Operations *ProjectsInstancesInstancePartitionsOperationsService
}

func NewProjectsInstancesInstancePartitionsOperationsService(s *Service) *ProjectsInstancesInstancePartitionsOperationsService {
	rs := &ProjectsInstancesInstancePartitionsOperationsService{s: s}
	return rs
}

type ProjectsInstancesInstancePartitionsOperationsService struct {
	s *Service
}

func NewProjectsInstancesOperationsService(s *Service) *ProjectsInstancesOperationsService {
	rs := &ProjectsInstancesOperationsService{s: s}
	return rs
}

type ProjectsInstancesOperationsService struct {
	s *Service
}

func NewScansService(s *Service) *ScansService {
	rs := &ScansService{s: s}
	return rs
}

type ScansService struct {
	s *Service
}

// Ack: Arguments to ack operations.
type Ack struct {
	// IgnoreNotFound: By default, an attempt to ack a message that does not exist
	// will fail with a `NOT_FOUND` error. With `ignore_not_found` set to true, the
	// ack will succeed even if the message does not exist. This is useful for
	// unconditionally acking a message, even if it is missing or has already been
	// acked.
	IgnoreNotFound bool `json:"ignoreNotFound,omitempty"`
	// Key: Required. The primary key of the message to be acked.
	Key []interface{} `json:"key,omitempty"`
	// Queue: Required. The queue where the message to be acked is stored.
	Queue string `json:"queue,omitempty"`
	// ForceSendFields is a list of field names (e.g. "IgnoreNotFound") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "IgnoreNotFound") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Ack) MarshalJSON() ([]byte, error) {
	type NoMethod Ack
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AdaptMessageRequest: Message sent by the client to the adapter.
type AdaptMessageRequest struct {
	// Attachments: Optional. Opaque request state passed by the client to the
	// server.
	Attachments map[string]string `json:"attachments,omitempty"`
	// Payload: Optional. Uninterpreted bytes from the underlying wire protocol.
	Payload string `json:"payload,omitempty"`
	// Protocol: Required. Identifier for the underlying wire protocol.
	Protocol string `json:"protocol,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Attachments") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Attachments") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AdaptMessageRequest) MarshalJSON() ([]byte, error) {
	type NoMethod AdaptMessageRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AdaptMessageResponse: Message sent by the adapter to the client.
type AdaptMessageResponse struct {
	// Last: Optional. Indicates whether this is the last AdaptMessageResponse in
	// the stream. This field may be optionally set by the server. Clients should
	// not rely on this field being set in all cases.
	Last bool `json:"last,omitempty"`
	// Payload: Optional. Uninterpreted bytes from the underlying wire protocol.
	Payload string `json:"payload,omitempty"`
	// StateUpdates: Optional. Opaque state updates to be applied by the client.
	StateUpdates map[string]string `json:"stateUpdates,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Last") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Last") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AdaptMessageResponse) MarshalJSON() ([]byte, error) {
	type NoMethod AdaptMessageResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AdapterSession: A session in the Cloud Spanner Adapter API.
type AdapterSession struct {
	// Name: Identifier. The name of the session. This is always system-assigned.
	Name string `json:"name,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Name") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Name") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AdapterSession) MarshalJSON() ([]byte, error) {
	type NoMethod AdapterSession
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AddSplitPointsRequest: The request for AddSplitPoints.
type AddSplitPointsRequest struct {
	// Initiator: Optional. A user-supplied tag associated with the split points.
	// For example, "initial_data_load", "special_event_1". Defaults to
	// "CloudAddSplitPointsAPI" if not specified. The length of the tag must not
	// exceed 50 characters, or else it is trimmed. Only valid UTF8 characters are
	// allowed.
	Initiator string `json:"initiator,omitempty"`
	// SplitPoints: Required. The split points to add.
	SplitPoints []*SplitPoints `json:"splitPoints,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Initiator") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Initiator") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AddSplitPointsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod AddSplitPointsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AddSplitPointsResponse: The response for AddSplitPoints.
type AddSplitPointsResponse struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// AsymmetricAutoscalingOption: AsymmetricAutoscalingOption specifies the
// scaling of replicas identified by the given selection.
type AsymmetricAutoscalingOption struct {
	// Overrides: Optional. Overrides applied to the top-level autoscaling
	// configuration for the selected replicas.
	Overrides *AutoscalingConfigOverrides `json:"overrides,omitempty"`
	// ReplicaSelection: Required. Selects the replicas to which this
	// AsymmetricAutoscalingOption applies. Only read-only replicas are supported.
	ReplicaSelection *InstanceReplicaSelection `json:"replicaSelection,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Overrides") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Overrides") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AsymmetricAutoscalingOption) MarshalJSON() ([]byte, error) {
	type NoMethod AsymmetricAutoscalingOption
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutoscalingConfig: Autoscaling configuration for an instance.
type AutoscalingConfig struct {
	// AsymmetricAutoscalingOptions: Optional. Optional asymmetric autoscaling
	// options. Replicas matching the replica selection criteria will be autoscaled
	// independently from other replicas. The autoscaler will scale the replicas
	// based on the utilization of replicas identified by the replica selection.
	// Replica selections should not overlap with each other. Other replicas (those
	// do not match any replica selection) will be autoscaled together and will
	// have the same compute capacity allocated to them.
	AsymmetricAutoscalingOptions []*AsymmetricAutoscalingOption `json:"asymmetricAutoscalingOptions,omitempty"`
	// AutoscalingLimits: Required. Autoscaling limits for an instance.
	AutoscalingLimits *AutoscalingLimits `json:"autoscalingLimits,omitempty"`
	// AutoscalingTargets: Required. The autoscaling targets for an instance.
	AutoscalingTargets *AutoscalingTargets `json:"autoscalingTargets,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "AsymmetricAutoscalingOptions") to unconditionally include in API requests.
	// By default, fields with empty or default values are omitted from API
	// requests. See https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields
	// for more details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AsymmetricAutoscalingOptions") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AutoscalingConfig) MarshalJSON() ([]byte, error) {
	type NoMethod AutoscalingConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutoscalingConfigOverrides: Overrides the top-level autoscaling
// configuration for the replicas identified by `replica_selection`. All fields
// in this message are optional. Any unspecified fields will use the
// corresponding values from the top-level autoscaling configuration.
type AutoscalingConfigOverrides struct {
	// AutoscalingLimits: Optional. If specified, overrides the min/max limit in
	// the top-level autoscaling configuration for the selected replicas.
	AutoscalingLimits *AutoscalingLimits `json:"autoscalingLimits,omitempty"`
	// AutoscalingTargetHighPriorityCpuUtilizationPercent: Optional. If specified,
	// overrides the autoscaling target high_priority_cpu_utilization_percent in
	// the top-level autoscaling configuration for the selected replicas.
	AutoscalingTargetHighPriorityCpuUtilizationPercent int64 `json:"autoscalingTargetHighPriorityCpuUtilizationPercent,omitempty"`
	// AutoscalingTargetTotalCpuUtilizationPercent: Optional. If specified,
	// overrides the autoscaling target `total_cpu_utilization_percent` in the
	// top-level autoscaling configuration for the selected replicas.
	AutoscalingTargetTotalCpuUtilizationPercent int64 `json:"autoscalingTargetTotalCpuUtilizationPercent,omitempty"`
	// DisableHighPriorityCpuAutoscaling: Optional. If true, disables high priority
	// CPU autoscaling for the selected replicas and ignores
	// high_priority_cpu_utilization_percent in the top-level autoscaling
	// configuration. When setting this field to true, setting
	// autoscaling_target_high_priority_cpu_utilization_percent field to a non-zero
	// value for the same replica is not supported. If false, the
	// autoscaling_target_high_priority_cpu_utilization_percent field in the
	// replica will be used if set to a non-zero value. Otherwise, the
	// high_priority_cpu_utilization_percent field in the top-level autoscaling
	// configuration will be used. Setting both
	// disable_high_priority_cpu_autoscaling and disable_total_cpu_autoscaling to
	// true for the same replica is not supported.
	DisableHighPriorityCpuAutoscaling bool `json:"disableHighPriorityCpuAutoscaling,omitempty"`
	// DisableTotalCpuAutoscaling: Optional. If true, disables total CPU
	// autoscaling for the selected replicas and ignores
	// total_cpu_utilization_percent in the top-level autoscaling configuration.
	// When setting this field to true, setting
	// autoscaling_target_total_cpu_utilization_percent field to a non-zero value
	// for the same replica is not supported. If false, the
	// autoscaling_target_total_cpu_utilization_percent field in the replica will
	// be used if set to a non-zero value. Otherwise, the
	// total_cpu_utilization_percent field in the top-level autoscaling
	// configuration will be used. Setting both
	// disable_high_priority_cpu_autoscaling and disable_total_cpu_autoscaling to
	// true for the same replica is not supported.
	DisableTotalCpuAutoscaling bool `json:"disableTotalCpuAutoscaling,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AutoscalingLimits") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AutoscalingLimits") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AutoscalingConfigOverrides) MarshalJSON() ([]byte, error) {
	type NoMethod AutoscalingConfigOverrides
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutoscalingLimits: The autoscaling limits for the instance. Users can define
// the minimum and maximum compute capacity allocated to the instance, and the
// autoscaler will only scale within that range. Users can either use nodes or
// processing units to specify the limits, but should use the same unit to set
// both the min_limit and max_limit.
type AutoscalingLimits struct {
	// MaxNodes: Maximum number of nodes allocated to the instance. If set, this
	// number should be greater than or equal to min_nodes.
	MaxNodes int64 `json:"maxNodes,omitempty"`
	// MaxProcessingUnits: Maximum number of processing units allocated to the
	// instance. If set, this number should be multiples of 1000 and be greater
	// than or equal to min_processing_units.
	MaxProcessingUnits int64 `json:"maxProcessingUnits,omitempty"`
	// MinNodes: Minimum number of nodes allocated to the instance. If set, this
	// number should be greater than or equal to 1.
	MinNodes int64 `json:"minNodes,omitempty"`
	// MinProcessingUnits: Minimum number of processing units allocated to the
	// instance. If set, this number should be multiples of 1000.
	MinProcessingUnits int64 `json:"minProcessingUnits,omitempty"`
	// ForceSendFields is a list of field names (e.g. "MaxNodes") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "MaxNodes") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s AutoscalingLimits) MarshalJSON() ([]byte, error) {
	type NoMethod AutoscalingLimits
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// AutoscalingTargets: The autoscaling targets for an instance.
type AutoscalingTargets struct {
	// HighPriorityCpuUtilizationPercent: Optional. The target high priority cpu
	// utilization percentage that the autoscaler should be trying to achieve for
	// the instance. This number is on a scale from 0 (no utilization) to 100 (full
	// utilization). The valid range is [10, 90] inclusive. If not specified or set
	// to 0, the autoscaler skips scaling based on high priority CPU utilization.
	HighPriorityCpuUtilizationPercent int64 `json:"highPriorityCpuUtilizationPercent,omitempty"`
	// StorageUtilizationPercent: Required. The target storage utilization
	// percentage that the autoscaler should be trying to achieve for the instance.
	// This number is on a scale from 0 (no utilization) to 100 (full utilization).
	// The valid range is [10, 99] inclusive.
	StorageUtilizationPercent int64 `json:"storageUtilizationPercent,omitempty"`
	// TotalCpuUtilizationPercent: Optional. The target total CPU utilization
	// percentage that the autoscaler should be trying to achieve for the instance.
	// This number is on a scale from 0 (no utilization) to 100 (full utilization).
	// The valid range is [10, 90] inclusive. If not specified or set to 0, the
	// autoscaler skips scaling based on total CPU utilization. If both
	// `high_priority_cpu_utilization_percent` and `total_cpu_utilization_percent`
	// are specified, the autoscaler provisions the larger of the two required
	// compute capacities to satisfy both targets.
	TotalCpuUtilizationPercent int64 `json:"totalCpuUtilizationPercent,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "HighPriorityCpuUtilizationPercent") to unconditionally include in API
	// requests. By default, fields with empty or default values are omitted from
	// API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g.
	// "HighPriorityCpuUtilizationPercent") to include in API requests with the
	// JSON null value. By default, fields with empty values are omitted from API
	// requests. See https://pkg.go.dev/google.golang.org/api#hdr-NullFields for
	// more details.
	NullFields []string `json:"-"`
}

func (s AutoscalingTargets) MarshalJSON() ([]byte, error) {
	type NoMethod AutoscalingTargets
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Backup: A backup of a Cloud Spanner database.
type Backup struct {
	// BackupSchedules: Output only. List of backup schedule URIs that are
	// associated with creating this backup. This is only applicable for scheduled
	// backups, and is empty for on-demand backups. To optimize for storage,
	// whenever possible, multiple schedules are collapsed together to create one
	// backup. In such cases, this field captures the list of all backup schedule
	// URIs that are associated with creating this backup. If collapsing is not
	// done, then this field captures the single backup schedule URI associated
	// with creating this backup.
	BackupSchedules []string `json:"backupSchedules,omitempty"`
	// CreateTime: Output only. The time the CreateBackup request is received. If
	// the request does not specify `version_time`, the `version_time` of the
	// backup will be equivalent to the `create_time`.
	CreateTime string `json:"createTime,omitempty"`
	// Database: Required for the CreateBackup operation. Name of the database from
	// which this backup was created. This needs to be in the same instance as the
	// backup. Values are of the form
	// `projects/{project}/instances/{instance}/databases/{database}`.
	Database string `json:"database,omitempty"`
	// DatabaseDialect: Output only. The database dialect information for the
	// backup.
	//
	// Possible values:
	//   "DATABASE_DIALECT_UNSPECIFIED" - Default value. This value will create a
	// database with the GOOGLE_STANDARD_SQL dialect.
	//   "GOOGLE_STANDARD_SQL" - GoogleSQL supported SQL.
	//   "POSTGRESQL" - PostgreSQL supported SQL.
	DatabaseDialect string `json:"databaseDialect,omitempty"`
	// EncryptionInfo: Output only. The encryption information for the backup.
	EncryptionInfo *EncryptionInfo `json:"encryptionInfo,omitempty"`
	// EncryptionInformation: Output only. The encryption information for the
	// backup, whether it is protected by one or more KMS keys. The information
	// includes all Cloud KMS key versions used to encrypt the backup. The
	// `encryption_status` field inside of each `EncryptionInfo` is not populated.
	// At least one of the key versions must be available for the backup to be
	// restored. If a key version is revoked in the middle of a restore, the
	// restore behavior is undefined.
	EncryptionInformation []*EncryptionInfo `json:"encryptionInformation,omitempty"`
	// ExclusiveSizeBytes: Output only. For a backup in an incremental backup
	// chain, this is the storage space needed to keep the data that has changed
	// since the previous backup. For all other backups, this is always the size of
	// the backup. This value may change if backups on the same chain get deleted
	// or expired. This field can be used to calculate the total storage space used
	// by a set of backups. For example, the total space used by all backups of a
	// database can be computed by summing up this field.
	ExclusiveSizeBytes int64 `json:"exclusiveSizeBytes,omitempty,string"`
	// ExpireTime: Required for the CreateBackup operation. The expiration time of
	// the backup, with microseconds granularity that must be at least 6 hours and
	// at most 366 days from the time the CreateBackup request is processed. Once
	// the `expire_time` has passed, the backup is eligible to be automatically
	// deleted by Cloud Spanner to free the resources used by the backup.
	ExpireTime string `json:"expireTime,omitempty"`
	// FreeableSizeBytes: Output only. The number of bytes that will be freed by
	// deleting this backup. This value will be zero if, for example, this backup
	// is part of an incremental backup chain and younger backups in the chain
	// require that we keep its data. For backups not in an incremental backup
	// chain, this is always the size of the backup. This value may change if
	// backups on the same chain get created, deleted or expired.
	FreeableSizeBytes int64 `json:"freeableSizeBytes,omitempty,string"`
	// IncrementalBackupChainId: Output only. Populated only for backups in an
	// incremental backup chain. Backups share the same chain id if and only if
	// they belong to the same incremental backup chain. Use this field to
	// determine which backups are part of the same incremental backup chain. The
	// ordering of backups in the chain can be determined by ordering the backup
	// `version_time`.
	IncrementalBackupChainId string `json:"incrementalBackupChainId,omitempty"`
	// InstancePartitions: Output only. The instance partition storing the backup.
	// This is the same as the list of the instance partitions that the database
	// recorded at the backup's `version_time`.
	InstancePartitions []*BackupInstancePartition `json:"instancePartitions,omitempty"`
	// MaxExpireTime: Output only. The max allowed expiration time of the backup,
	// with microseconds granularity. A backup's expiration time can be configured
	// in multiple APIs: CreateBackup, UpdateBackup, CopyBackup. When updating or
	// copying an existing backup, the expiration time specified must be less than
	// `Backup.max_expire_time`.
	MaxExpireTime string `json:"maxExpireTime,omitempty"`
	// MinimumRestorableEdition: Output only. The minimum edition required to
	// successfully restore the backup. Populated only if the edition is Enterprise
	// or Enterprise Plus.
	//
	// Possible values:
	//   "EDITION_UNSPECIFIED" - Edition not specified.
	//   "STANDARD" - Standard edition.
	//   "ENTERPRISE" - Enterprise edition.
	//   "ENTERPRISE_PLUS" - Enterprise Plus edition.
	MinimumRestorableEdition string `json:"minimumRestorableEdition,omitempty"`
	// Name: Output only for the CreateBackup operation. Required for the
	// UpdateBackup operation. A globally unique identifier for the backup which
	// cannot be changed. Values are of the form
	// `projects/{project}/instances/{instance}/backups/a-z*[a-z0-9]` The final
	// segment of the name must be between 2 and 60 characters in length. The
	// backup is stored in the location(s) specified in the instance configuration
	// of the instance containing the backup, identified by the prefix of the
	// backup name of the form `projects/{project}/instances/{instance}`.
	Name string `json:"name,omitempty"`
	// OldestVersionTime: Output only. Data deleted at a time older than this is
	// guaranteed not to be retained in order to support this backup. For a backup
	// in an incremental backup chain, this is the version time of the oldest
	// backup that exists or ever existed in the chain. For all other backups, this
	// is the version time of the backup. This field can be used to understand what
	// data is being retained by the backup system.
	OldestVersionTime string `json:"oldestVersionTime,omitempty"`
	// ReferencingBackups: Output only. The names of the destination backups being
	// created by copying this source backup. The backup names are of the form
	// `projects/{project}/instances/{instance}/backups/{backup}`. Referencing
	// backups may exist in different instances. The existence of any referencing
	// backup prevents the backup from being deleted. When the copy operation is
	// done (either successfully completed or cancelled or the destination backup
	// is deleted), the reference to the backup is removed.
	ReferencingBackups []string `json:"referencingBackups,omitempty"`
	// ReferencingDatabases: Output only. The names of the restored databases that
	// reference the backup. The database names are of the form
	// `projects/{project}/instances/{instance}/databases/{database}`. Referencing
	// databases may exist in different instances. The existence of any referencing
	// database prevents the backup from being deleted. When a restored database
	// from the backup enters the `READY` state, the reference to the backup is
	// removed.
	ReferencingDatabases []string `json:"referencingDatabases,omitempty"`
	// SizeBytes: Output only. Size of the backup in bytes. For a backup in an
	// incremental backup chain, this is the sum of the `exclusive_size_bytes` of
	// itself and all older backups in the chain.
	SizeBytes int64 `json:"sizeBytes,omitempty,string"`
	// State: Output only. The current state of the backup.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Not specified.
	//   "CREATING" - The pending backup is still being created. Operations on the
	// backup may fail with `FAILED_PRECONDITION` in this state.
	//   "READY" - The backup is complete and ready for use.
	State string `json:"state,omitempty"`
	// VersionTime: The backup will contain an externally consistent copy of the
	// database at the timestamp specified by `version_time`. If `version_time` is
	// not specified, the system will set `version_time` to the `create_time` of
	// the backup.
	VersionTime string `json:"versionTime,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "BackupSchedules") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BackupSchedules") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Backup) MarshalJSON() ([]byte, error) {
	type NoMethod Backup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BackupInfo: Information about a backup.
type BackupInfo struct {
	// Backup: Name of the backup.
	Backup string `json:"backup,omitempty"`
	// CreateTime: The time the CreateBackup request was received.
	CreateTime string `json:"createTime,omitempty"`
	// SourceDatabase: Name of the database the backup was created from.
	SourceDatabase string `json:"sourceDatabase,omitempty"`
	// VersionTime: The backup contains an externally consistent copy of
	// `source_database` at the timestamp specified by `version_time`. If the
	// CreateBackup request did not specify `version_time`, the `version_time` of
	// the backup is equivalent to the `create_time`.
	VersionTime string `json:"versionTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Backup") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Backup") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BackupInfo) MarshalJSON() ([]byte, error) {
	type NoMethod BackupInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BackupInstancePartition: Instance partition information for the backup.
type BackupInstancePartition struct {
	// InstancePartition: A unique identifier for the instance partition. Values
	// are of the form
	// `projects/{project}/instances/{instance}/instancePartitions/{instance_partiti
	// on_id}`
	InstancePartition string `json:"instancePartition,omitempty"`
	// ForceSendFields is a list of field names (e.g. "InstancePartition") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "InstancePartition") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BackupInstancePartition) MarshalJSON() ([]byte, error) {
	type NoMethod BackupInstancePartition
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BackupSchedule: BackupSchedule expresses the automated backup creation
// specification for a Spanner database.
type BackupSchedule struct {
	// EncryptionConfig: Optional. The encryption configuration that is used to
	// encrypt the backup. If this field is not specified, the backup uses the same
	// encryption configuration as the database.
	EncryptionConfig *CreateBackupEncryptionConfig `json:"encryptionConfig,omitempty"`
	// FullBackupSpec: The schedule creates only full backups.
	FullBackupSpec *FullBackupSpec `json:"fullBackupSpec,omitempty"`
	// IncrementalBackupSpec: The schedule creates incremental backup chains.
	IncrementalBackupSpec *IncrementalBackupSpec `json:"incrementalBackupSpec,omitempty"`
	// Name: Identifier. Output only for the CreateBackupSchedule operation.
	// Required for the UpdateBackupSchedule operation. A globally unique
	// identifier for the backup schedule which cannot be changed. Values are of
	// the form `projects//instances//databases//backupSchedules/a-z*[a-z0-9]` The
	// final segment of the name must be between 2 and 60 characters in length.
	Name string `json:"name,omitempty"`
	// RetentionDuration: Optional. The retention duration of a backup that must be
	// at least 6 hours and at most 366 days. The backup is eligible to be
	// automatically deleted once the retention period has elapsed.
	RetentionDuration string `json:"retentionDuration,omitempty"`
	// Spec: Optional. The schedule specification based on which the backup
	// creations are triggered.
	Spec *BackupScheduleSpec `json:"spec,omitempty"`
	// UpdateTime: Output only. The timestamp at which the schedule was last
	// updated. If the schedule has never been updated, this field contains the
	// timestamp when the schedule was first created.
	UpdateTime string `json:"updateTime,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "EncryptionConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EncryptionConfig") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BackupSchedule) MarshalJSON() ([]byte, error) {
	type NoMethod BackupSchedule
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BackupScheduleSpec: Defines specifications of the backup schedule.
type BackupScheduleSpec struct {
	// CronSpec: Cron style schedule specification.
	CronSpec *CrontabSpec `json:"cronSpec,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CronSpec") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CronSpec") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BackupScheduleSpec) MarshalJSON() ([]byte, error) {
	type NoMethod BackupScheduleSpec
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchCreateSessionsRequest: The request for BatchCreateSessions.
type BatchCreateSessionsRequest struct {
	// SessionCount: Required. The number of sessions to be created in this batch
	// call. At least one session is created. The API can return fewer than the
	// requested number of sessions. If a specific number of sessions are desired,
	// the client can make additional calls to `BatchCreateSessions` (adjusting
	// session_count as necessary).
	SessionCount int64 `json:"sessionCount,omitempty"`
	// SessionTemplate: Parameters to apply to each created session.
	SessionTemplate *Session `json:"sessionTemplate,omitempty"`
	// ForceSendFields is a list of field names (e.g. "SessionCount") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "SessionCount") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BatchCreateSessionsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod BatchCreateSessionsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchCreateSessionsResponse: The response for BatchCreateSessions.
type BatchCreateSessionsResponse struct {
	// Session: The freshly created sessions.
	Session []*Session `json:"session,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Session") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Session") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BatchCreateSessionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod BatchCreateSessionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchWriteRequest: The request for BatchWrite.
type BatchWriteRequest struct {
	// ExcludeTxnFromChangeStreams: Optional. If you don't set the
	// `exclude_txn_from_change_streams` option or if it's set to `false`, then any
	// change streams monitoring columns modified by transactions will capture the
	// updates made within that transaction.
	ExcludeTxnFromChangeStreams bool `json:"excludeTxnFromChangeStreams,omitempty"`
	// MutationGroups: Required. The groups of mutations to be applied.
	MutationGroups []*MutationGroup `json:"mutationGroups,omitempty"`
	// RequestOptions: Common options for this request.
	RequestOptions *RequestOptions `json:"requestOptions,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "ExcludeTxnFromChangeStreams") to unconditionally include in API requests.
	// By default, fields with empty or default values are omitted from API
	// requests. See https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields
	// for more details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExcludeTxnFromChangeStreams") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BatchWriteRequest) MarshalJSON() ([]byte, error) {
	type NoMethod BatchWriteRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BatchWriteResponse: The result of applying a batch of mutations.
type BatchWriteResponse struct {
	// CommitTimestamp: The commit timestamp of the transaction that applied this
	// batch. Present if status is OK and the mutation groups were applied, absent
	// otherwise. For mutation groups with conditions, a status=OK and missing
	// commit_timestamp means that the mutation groups were not applied due to the
	// condition not being satisfied after evaluation.
	CommitTimestamp string `json:"commitTimestamp,omitempty"`
	// Indexes: The mutation groups applied in this batch. The values index into
	// the `mutation_groups` field in the corresponding `BatchWriteRequest`.
	Indexes []int64 `json:"indexes,omitempty"`
	// Status: An `OK` status indicates success. Any other status indicates a
	// failure.
	Status *Status `json:"status,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "CommitTimestamp") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CommitTimestamp") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BatchWriteResponse) MarshalJSON() ([]byte, error) {
	type NoMethod BatchWriteResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// BeginTransactionRequest: The request for BeginTransaction.
type BeginTransactionRequest struct {
	// MutationKey: Optional. Required for read-write transactions on a multiplexed
	// session that commit mutations but don't perform any reads or queries. You
	// must randomly select one of the mutations from the mutation set and send it
	// as a part of this request.
	MutationKey *Mutation `json:"mutationKey,omitempty"`
	// Options: Required. Options for the new transaction.
	Options *TransactionOptions `json:"options,omitempty"`
	// RequestOptions: Common options for this request. Priority is ignored for
	// this request. Setting the priority in this `request_options` struct doesn't
	// do anything. To set the priority for a transaction, set it on the reads and
	// writes that are part of this transaction instead.
	RequestOptions *RequestOptions `json:"requestOptions,omitempty"`
	// ForceSendFields is a list of field names (e.g. "MutationKey") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "MutationKey") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s BeginTransactionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod BeginTransactionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Binding: Associates `members`, or principals, with a `role`.
type Binding struct {
	// Condition: The condition that is associated with this binding. If the
	// condition evaluates to `true`, then this binding applies to the current
	// request. If the condition evaluates to `false`, then this binding does not
	// apply to the current request. However, a different role binding might grant
	// the same role to one or more of the principals in this binding. To learn
	// which resources support conditions in their IAM policies, see the IAM
	// documentation
	// (https://cloud.google.com/iam/help/conditions/resource-policies).
	Condition *Expr `json:"condition,omitempty"`
	// Members: Specifies the principals requesting access for a Google Cloud
	// resource. `members` can have the following values: * `allUsers`: A special
	// identifier that represents anyone who is on the internet; with or without a
	// Google account. * `allAuthenticatedUsers`: A special identifier that
	// represents anyone who is authenticated with a Google account or a service
	// account. Does not include identities that come from external identity
	// providers (IdPs) through identity federation. * `user:{emailid}`: An email
	// address that represents a specific Google account. For example,
	// `alice@example.com` . * `serviceAccount:{emailid}`: An email address that
	// represents a Google service account. For example,
	// `my-other-app@appspot.gserviceaccount.com`. *
	// `serviceAccount:{projectid}.svc.id.goog[{namespace}/{kubernetes-sa}]`: An
	// identifier for a Kubernetes service account
	// (https://cloud.google.com/kubernetes-engine/docs/how-to/kubernetes-service-accounts).
	// For example, `my-project.svc.id.goog[my-namespace/my-kubernetes-sa]`. *
	// `group:{emailid}`: An email address that represents a Google group. For
	// example, `admins@example.com`. * `domain:{domain}`: The G Suite domain
	// (primary) that represents all the users of that domain. For example,
	// `google.com` or `example.com`. *
	// `principal://iam.googleapis.com/locations/global/workforcePools/{pool_id}/sub
	// ject/{subject_attribute_value}`: A single identity in a workforce identity
	// pool. *
	// `principalSet://iam.googleapis.com/locations/global/workforcePools/{pool_id}/
	// group/{group_id}`: All workforce identities in a group. *
	// `principalSet://iam.googleapis.com/locations/global/workforcePools/{pool_id}/
	// attribute.{attribute_name}/{attribute_value}`: All workforce identities with
	// a specific attribute value. *
	// `principalSet://iam.googleapis.com/locations/global/workforcePools/{pool_id}/
	// *`: All identities in a workforce identity pool. *
	// `principal://iam.googleapis.com/projects/{project_number}/locations/global/wo
	// rkloadIdentityPools/{pool_id}/subject/{subject_attribute_value}`: A single
	// identity in a workload identity pool. *
	// `principalSet://iam.googleapis.com/projects/{project_number}/locations/global
	// /workloadIdentityPools/{pool_id}/group/{group_id}`: A workload identity pool
	// group. *
	// `principalSet://iam.googleapis.com/projects/{project_number}/locations/global
	// /workloadIdentityPools/{pool_id}/attribute.{attribute_name}/{attribute_value}
	// `: All identities in a workload identity pool with a certain attribute. *
	// `principalSet://iam.googleapis.com/projects/{project_number}/locations/global
	// /workloadIdentityPools/{pool_id}/*`: All identities in a workload identity
	// pool. * `deleted:user:{emailid}?uid={uniqueid}`: An email address (plus
	// unique identifier) representing a user that has been recently deleted. For
	// example, `alice@example.com?uid=123456789012345678901`. If the user is
	// recovered, this value reverts to `user:{emailid}` and the recovered user
	// retains the role in the binding. *
	// `deleted:serviceAccount:{emailid}?uid={uniqueid}`: An email address (plus
	// unique identifier) representing a service account that has been recently
	// deleted. For example,
	// `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. If the
	// service account is undeleted, this value reverts to
	// `serviceAccount:{emailid}` and the undeleted service account retains the
	// role in the binding. * `deleted:group:{emailid}?uid={uniqueid}`: An email
	// address (plus unique identifier) representing a Google group that has been
	// recently deleted. For example,
	// `admins@example.com?uid=123456789012345678901`. If the group is recovered,
	// this value reverts to `group:{emailid}` and the recovered group retains the
	// role in the binding. *
	// `deleted:principal://iam.googleapis.com/locations/global/workforcePools/{pool
	// _id}/subject/{subject_attribute_value}`: Deleted single identity in a
	// workforce identity pool. For example,
	// `deleted:principal://iam.googleapis.com/locations/global/workforcePools/my-po
	// ol-id/subject/my-subject-attribute-value`.
	Members []string `json:"members,omitempty"`
	// Role: Role that is assigned to the list of `members`, or principals. For
	// example, `roles/viewer`, `roles/editor`, or `roles/owner`. For an overview
	// of the IAM roles and permissions, see the IAM documentation
	// (https://cloud.google.com/iam/docs/roles-overview). For a list of the
	// available pre-defined roles, see here
	// (https://cloud.google.com/iam/docs/understanding-roles).
	Role string `json:"role,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Condition") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Condition") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Binding) MarshalJSON() ([]byte, error) {
	type NoMethod Binding
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ChangeQuorumMetadata: Metadata type for the long-running operation returned
// by ChangeQuorum.
type ChangeQuorumMetadata struct {
	// EndTime: If set, the time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// Request: The request for ChangeQuorum.
	Request *ChangeQuorumRequest `json:"request,omitempty"`
	// StartTime: Time the request was received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EndTime") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EndTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ChangeQuorumMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod ChangeQuorumMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ChangeQuorumRequest: The request for ChangeQuorum.
type ChangeQuorumRequest struct {
	// Etag: Optional. The etag is the hash of the `QuorumInfo`. The `ChangeQuorum`
	// operation is only performed if the etag matches that of the `QuorumInfo` in
	// the current database resource. Otherwise the API returns an `ABORTED` error.
	// The etag is used for optimistic concurrency control as a way to help prevent
	// simultaneous change quorum requests that could create a race condition.
	Etag string `json:"etag,omitempty"`
	// Name: Required. Name of the database in which to apply `ChangeQuorum`.
	// Values are of the form `projects//instances//databases/`.
	Name string `json:"name,omitempty"`
	// QuorumType: Required. The type of this quorum.
	QuorumType *QuorumType `json:"quorumType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Etag") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Etag") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ChangeQuorumRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ChangeQuorumRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ChangeStreamRecord: Spanner Change Streams enable customers to capture and
// stream out changes to their Spanner databases in real-time. A change stream
// can be created with option partition_mode='IMMUTABLE_KEY_RANGE' or
// partition_mode='MUTABLE_KEY_RANGE'. This message is only used in Change
// Streams created with the option partition_mode='MUTABLE_KEY_RANGE'. Spanner
// automatically creates a special Table-Valued Function (TVF) along with each
// Change Streams. The function provides access to the change stream's records.
// The function is named READ_ (where is the name of the change stream), and it
// returns a table with only one column called ChangeRecord.
type ChangeStreamRecord struct {
	// DataChangeRecord: Data change record describing a data change for a change
	// stream partition.
	DataChangeRecord *DataChangeRecord `json:"dataChangeRecord,omitempty"`
	// HeartbeatRecord: Heartbeat record describing a heartbeat for a change stream
	// partition.
	HeartbeatRecord *HeartbeatRecord `json:"heartbeatRecord,omitempty"`
	// PartitionEndRecord: Partition end record describing a terminated change
	// stream partition.
	PartitionEndRecord *PartitionEndRecord `json:"partitionEndRecord,omitempty"`
	// PartitionEventRecord: Partition event record describing key range changes
	// for a change stream partition.
	PartitionEventRecord *PartitionEventRecord `json:"partitionEventRecord,omitempty"`
	// PartitionStartRecord: Partition start record describing a new change stream
	// partition.
	PartitionStartRecord *PartitionStartRecord `json:"partitionStartRecord,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DataChangeRecord") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DataChangeRecord") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ChangeStreamRecord) MarshalJSON() ([]byte, error) {
	type NoMethod ChangeStreamRecord
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ChildLink: Metadata associated with a parent-child relationship appearing in
// a PlanNode.
type ChildLink struct {
	// ChildIndex: The node to which the link points.
	ChildIndex int64 `json:"childIndex,omitempty"`
	// Type: The type of the link. For example, in Hash Joins this could be used to
	// distinguish between the build child and the probe child, or in the case of
	// the child being an output variable, to represent the tag associated with the
	// output variable.
	Type string `json:"type,omitempty"`
	// Variable: Only present if the child node is SCALAR and corresponds to an
	// output variable of the parent node. The field carries the name of the output
	// variable. For example, a `TableScan` operator that reads rows from a table
	// will have child links to the `SCALAR` nodes representing the output
	// variables created for each column that is read by the operator. The
	// corresponding `variable` fields will be set to the variable names assigned
	// to the columns.
	Variable string `json:"variable,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ChildIndex") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ChildIndex") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ChildLink) MarshalJSON() ([]byte, error) {
	type NoMethod ChildLink
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ClientContext: Container for various pieces of client-owned context attached
// to a request.
type ClientContext struct {
	// SecureContext: Optional. Map of parameter name to value for this request.
	// These values will be returned by any SECURE_CONTEXT() calls invoked by this
	// request (e.g., by queries against Parameterized Secure Views).
	SecureContext googleapi.RawMessage `json:"secureContext,omitempty"`
	// ForceSendFields is a list of field names (e.g. "SecureContext") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "SecureContext") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ClientContext) MarshalJSON() ([]byte, error) {
	type NoMethod ClientContext
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ColumnMetadata: Metadata for a column.
type ColumnMetadata struct {
	// IsPrimaryKey: Indicates whether the column is a primary key column.
	IsPrimaryKey bool `json:"isPrimaryKey,omitempty"`
	// Name: Name of the column.
	Name string `json:"name,omitempty"`
	// OrdinalPosition: Ordinal position of the column based on the original table
	// definition in the schema starting with a value of 1.
	OrdinalPosition int64 `json:"ordinalPosition,omitempty,string"`
	// Type: Type of the column.
	Type *Type `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "IsPrimaryKey") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "IsPrimaryKey") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ColumnMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod ColumnMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CommitRequest: The request for Commit.
type CommitRequest struct {
	// MaxCommitDelay: Optional. The amount of latency this request is configured
	// to incur in order to improve throughput. If this field isn't set, Spanner
	// assumes requests are relatively latency sensitive and automatically
	// determines an appropriate delay time. You can specify a commit delay value
	// between 0 and 500 ms.
	MaxCommitDelay string `json:"maxCommitDelay,omitempty"`
	// Mutations: The mutations to be executed when this transaction commits. All
	// mutations are applied atomically, in the order they appear in this list.
	Mutations []*Mutation `json:"mutations,omitempty"`
	// PrecommitToken: Optional. If the read-write transaction was executed on a
	// multiplexed session, then you must include the precommit token with the
	// highest sequence number received in this transaction attempt. Failing to do
	// so results in a `FailedPrecondition` error.
	PrecommitToken *MultiplexedSessionPrecommitToken `json:"precommitToken,omitempty"`
	// RequestOptions: Common options for this request.
	RequestOptions *RequestOptions `json:"requestOptions,omitempty"`
	// ReturnCommitStats: If `true`, then statistics related to the transaction is
	// included in the CommitResponse. Default value is `false`.
	ReturnCommitStats bool `json:"returnCommitStats,omitempty"`
	// SingleUseTransaction: Execute mutations in a temporary transaction. Note
	// that unlike commit of a previously-started transaction, commit with a
	// temporary transaction is non-idempotent. That is, if the `CommitRequest` is
	// sent to Cloud Spanner more than once (for instance, due to retries in the
	// application, or in the transport library), it's possible that the mutations
	// are executed more than once. If this is undesirable, use BeginTransaction
	// and Commit instead.
	SingleUseTransaction *TransactionOptions `json:"singleUseTransaction,omitempty"`
	// TransactionId: Commit a previously-started transaction.
	TransactionId string `json:"transactionId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "MaxCommitDelay") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "MaxCommitDelay") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CommitRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CommitRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CommitResponse: The response for Commit.
type CommitResponse struct {
	// CommitStats: The statistics about this `Commit`. Not returned by default.
	// For more information, see CommitRequest.return_commit_stats.
	CommitStats *CommitStats `json:"commitStats,omitempty"`
	// CommitTimestamp: The Cloud Spanner timestamp at which the transaction
	// committed.
	CommitTimestamp string `json:"commitTimestamp,omitempty"`
	// IsolationLevel: The isolation level used for the read-write transaction.
	//
	// Possible values:
	//   "ISOLATION_LEVEL_UNSPECIFIED" - Default value. If the value is not
	// specified, the `SERIALIZABLE` isolation level is used.
	//   "SERIALIZABLE" - All transactions appear as if they executed in a serial
	// order, even if some of the reads, writes, and other operations of distinct
	// transactions actually occurred in parallel. Spanner assigns commit
	// timestamps that reflect the order of committed transactions to implement
	// this property. Spanner offers a stronger guarantee than serializability
	// called external consistency. For more information, see [TrueTime and
	// external
	// consistency](https://cloud.google.com/spanner/docs/true-time-external-consist
	// ency#serializability).
	//   "REPEATABLE_READ" - All reads performed during the transaction observe a
	// consistent snapshot of the database, and the transaction is only
	// successfully committed in the absence of conflicts between its updates and
	// any concurrent updates that have occurred since that snapshot. Consequently,
	// in contrast to `SERIALIZABLE` transactions, only write-write conflicts are
	// detected in snapshot transactions. This isolation level does not support
	// read-only and partitioned DML transactions. When `REPEATABLE_READ` is
	// specified on a read-write transaction, the locking semantics default to
	// `OPTIMISTIC`.
	IsolationLevel string `json:"isolationLevel,omitempty"`
	// PrecommitToken: If specified, transaction has not committed yet. You must
	// retry the commit with the new precommit token.
	PrecommitToken *MultiplexedSessionPrecommitToken `json:"precommitToken,omitempty"`
	// ReadLockMode: The read lock mode used for the read-write transaction.
	//
	// Possible values:
	//   "READ_LOCK_MODE_UNSPECIFIED" - Default value. * If isolation level is
	// SERIALIZABLE, locking semantics default to `PESSIMISTIC`. * If isolation
	// level is REPEATABLE_READ, locking semantics default to `OPTIMISTIC`. * See
	// [Concurrency
	// control](https://cloud.google.com/spanner/docs/concurrency-control) for more
	// details.
	//   "PESSIMISTIC" - Pessimistic lock mode. Lock acquisition behavior depends
	// on the isolation level in use. In SERIALIZABLE isolation, reads and writes
	// acquire necessary locks during transaction statement execution. In
	// REPEATABLE_READ isolation, reads that explicitly request to be locked and
	// writes acquire locks. See [Concurrency
	// control](https://cloud.google.com/spanner/docs/concurrency-control) for
	// details on the types of locks acquired at each transaction step.
	//   "OPTIMISTIC" - Optimistic lock mode. Lock acquisition behavior depends on
	// the isolation level in use. In both SERIALIZABLE and REPEATABLE_READ
	// isolation, reads and writes do not acquire locks during transaction
	// statement execution. See [Concurrency
	// control](https://cloud.google.com/spanner/docs/concurrency-control) for
	// details on how the guarantees of each isolation level are provided at commit
	// time.
	ReadLockMode string `json:"readLockMode,omitempty"`
	// SnapshotTimestamp: If `TransactionOptions.isolation_level` is set to
	// `IsolationLevel.REPEATABLE_READ`, then the snapshot timestamp is the
	// timestamp at which all reads in the transaction ran. This timestamp is never
	// returned.
	SnapshotTimestamp string `json:"snapshotTimestamp,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "CommitStats") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CommitStats") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CommitResponse) MarshalJSON() ([]byte, error) {
	type NoMethod CommitResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CommitStats: Additional statistics about a commit.
type CommitStats struct {
	// MutationCount: The total number of mutations for the transaction. Knowing
	// the `mutation_count` value can help you maximize the number of mutations in
	// a transaction and minimize the number of API round trips. You can also
	// monitor this value to prevent transactions from exceeding the system limit
	// (https://cloud.google.com/spanner/quotas#limits_for_creating_reading_updating_and_deleting_data).
	// If the number of mutations exceeds the limit, the server returns
	// INVALID_ARGUMENT
	// (https://cloud.google.com/spanner/docs/reference/rest/v1/Code#ENUM_VALUES.INVALID_ARGUMENT).
	MutationCount int64 `json:"mutationCount,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "MutationCount") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "MutationCount") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CommitStats) MarshalJSON() ([]byte, error) {
	type NoMethod CommitStats
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CompactDatabaseMetadata: Metadata type for the long-running operation
// returned by `CALL compact_all()`, which can be executed using ExecuteSql or
// ExecuteStreamingSql APIs.
type CompactDatabaseMetadata struct {
	// CancelTime: Output only. The time at which cancellation of this operation
	// was received. Operations.CancelOperation starts asynchronous cancellation on
	// a long-running operation. The server makes a best effort to cancel the
	// operation, but success is not guaranteed. Clients can use
	// Operations.GetOperation or other methods to check whether the cancellation
	// succeeded or whether the operation completed despite cancellation. On
	// successful cancellation, the operation is not deleted; instead, it becomes
	// an operation with an Operation.error value with a google.rpc.Status.code of
	// 1, corresponding to `Code.CANCELLED`.
	CancelTime string `json:"cancelTime,omitempty"`
	// Database: Output only. The database being compacted.
	Database string `json:"database,omitempty"`
	// Progress: Output only. The progress of the compaction operation.
	Progress *OperationProgress `json:"progress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CompactDatabaseMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CompactDatabaseMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ContextValue: A message representing context for a KeyRangeInfo, including a
// label, value, unit, and severity.
type ContextValue struct {
	// Label: The label for the context value. e.g. "latency".
	Label *LocalizedString `json:"label,omitempty"`
	// Severity: The severity of this context.
	//
	// Possible values:
	//   "SEVERITY_UNSPECIFIED" - Required default value.
	//   "INFO" - Lowest severity level "Info".
	//   "WARNING" - Middle severity level "Warning".
	//   "ERROR" - Severity level signaling an error "Error"
	//   "FATAL" - Severity level signaling a non recoverable error "Fatal"
	Severity string `json:"severity,omitempty"`
	// Unit: The unit of the context value.
	Unit string `json:"unit,omitempty"`
	// Value: The value for the context.
	Value float64 `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Label") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Label") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ContextValue) MarshalJSON() ([]byte, error) {
	type NoMethod ContextValue
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *ContextValue) UnmarshalJSON(data []byte) error {
	type NoMethod ContextValue
	var s1 struct {
		Value gensupport.JSONFloat64 `json:"value"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Value = float64(s1.Value)
	return nil
}

// CopyBackupEncryptionConfig: Encryption configuration for the copied backup.
type CopyBackupEncryptionConfig struct {
	// EncryptionType: Required. The encryption type of the backup.
	//
	// Possible values:
	//   "ENCRYPTION_TYPE_UNSPECIFIED" - Unspecified. Do not use.
	//   "USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION" - This is the default option for
	// CopyBackup when encryption_config is not specified. For example, if the
	// source backup is using `Customer_Managed_Encryption`, the backup will be
	// using the same Cloud KMS key as the source backup.
	//   "GOOGLE_DEFAULT_ENCRYPTION" - Use Google default encryption.
	//   "CUSTOMER_MANAGED_ENCRYPTION" - Use customer managed encryption. If
	// specified, either `kms_key_name` or `kms_key_names` must contain valid Cloud
	// KMS keys.
	EncryptionType string `json:"encryptionType,omitempty"`
	// KmsKeyName: Optional. This field is maintained for backwards compatibility.
	// For new callers, we recommend using `kms_key_names` to specify the KMS key.
	// Only use `kms_key_name` if the location of the KMS key matches the database
	// instance's configuration (location) exactly. For example, if the KMS
	// location is in `us-central1` or `nam3`, then the database instance must also
	// be in `us-central1` or `nam3`. The Cloud KMS key that is used to encrypt and
	// decrypt the restored database. Set this field only when encryption_type is
	// `CUSTOMER_MANAGED_ENCRYPTION`. Values are of the form
	// `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{kms_
	// key_name}`.
	KmsKeyName string `json:"kmsKeyName,omitempty"`
	// KmsKeyNames: Optional. Specifies the KMS configuration for the one or more
	// keys used to protect the backup. Values are of the form
	// `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{kms_
	// key_name}`. KMS keys specified can be in any order. The keys referenced by
	// `kms_key_names` must fully cover all regions of the backup's instance
	// configuration. Some examples: * For regional (single-region) instance
	// configurations, specify a regional location KMS key. * For multi-region
	// instance configurations of type `GOOGLE_MANAGED`, either specify a
	// multi-region location KMS key or multiple regional location KMS keys that
	// cover all regions in the instance configuration. * For an instance
	// configuration of type `USER_MANAGED`, specify only regional location KMS
	// keys to cover each region in the instance configuration. Multi-region
	// location KMS keys aren't supported for `USER_MANAGED` type instance
	// configurations.
	KmsKeyNames []string `json:"kmsKeyNames,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EncryptionType") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EncryptionType") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CopyBackupEncryptionConfig) MarshalJSON() ([]byte, error) {
	type NoMethod CopyBackupEncryptionConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CopyBackupMetadata: Metadata type for the operation returned by CopyBackup.
type CopyBackupMetadata struct {
	// CancelTime: The time at which cancellation of CopyBackup operation was
	// received. Operations.CancelOperation starts asynchronous cancellation on a
	// long-running operation. The server makes a best effort to cancel the
	// operation, but success is not guaranteed. Clients can use
	// Operations.GetOperation or other methods to check whether the cancellation
	// succeeded or whether the operation completed despite cancellation. On
	// successful cancellation, the operation is not deleted; instead, it becomes
	// an operation with an Operation.error value with a google.rpc.Status.code of
	// 1, corresponding to `Code.CANCELLED`.
	CancelTime string `json:"cancelTime,omitempty"`
	// Name: The name of the backup being created through the copy operation.
	// Values are of the form
	// `projects/{project}/instances/{instance}/backups/{backup}`.
	Name string `json:"name,omitempty"`
	// Progress: The progress of the CopyBackup operation.
	Progress *OperationProgress `json:"progress,omitempty"`
	// SourceBackup: The name of the source backup that is being copied. Values are
	// of the form `projects/{project}/instances/{instance}/backups/{backup}`.
	SourceBackup string `json:"sourceBackup,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CopyBackupMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CopyBackupMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CopyBackupRequest: The request for CopyBackup.
type CopyBackupRequest struct {
	// BackupId: Required. The id of the backup copy. The `backup_id` appended to
	// `parent` forms the full backup_uri of the form
	// `projects/{project}/instances/{instance}/backups/{backup}`.
	BackupId string `json:"backupId,omitempty"`
	// EncryptionConfig: Optional. The encryption configuration used to encrypt the
	// backup. If this field is not specified, the backup will use the same
	// encryption configuration as the source backup by default, namely
	// encryption_type = `USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION`.
	EncryptionConfig *CopyBackupEncryptionConfig `json:"encryptionConfig,omitempty"`
	// ExpireTime: Required. The expiration time of the backup in microsecond
	// granularity. The expiration time must be at least 6 hours and at most 366
	// days from the `create_time` of the source backup. Once the `expire_time` has
	// passed, the backup is eligible to be automatically deleted by Cloud Spanner
	// to free the resources used by the backup.
	ExpireTime string `json:"expireTime,omitempty"`
	// SourceBackup: Required. The source backup to be copied. The source backup
	// needs to be in READY state for it to be copied. Once CopyBackup is in
	// progress, the source backup cannot be deleted or cleaned up on expiration
	// until CopyBackup is finished. Values are of the form:
	// `projects/{project}/instances/{instance}/backups/{backup}`.
	SourceBackup string `json:"sourceBackup,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BackupId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BackupId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CopyBackupRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CopyBackupRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateBackupEncryptionConfig: Encryption configuration for the backup to
// create.
type CreateBackupEncryptionConfig struct {
	// EncryptionType: Required. The encryption type of the backup.
	//
	// Possible values:
	//   "ENCRYPTION_TYPE_UNSPECIFIED" - Unspecified. Do not use.
	//   "USE_DATABASE_ENCRYPTION" - Use the same encryption configuration as the
	// database. This is the default option when encryption_config is empty. For
	// example, if the database is using `Customer_Managed_Encryption`, the backup
	// will be using the same Cloud KMS key as the database.
	//   "GOOGLE_DEFAULT_ENCRYPTION" - Use Google default encryption.
	//   "CUSTOMER_MANAGED_ENCRYPTION" - Use customer managed encryption. If
	// specified, `kms_key_name` must contain a valid Cloud KMS key.
	EncryptionType string `json:"encryptionType,omitempty"`
	// KmsKeyName: Optional. This field is maintained for backwards compatibility.
	// For new callers, we recommend using `kms_key_names` to specify the KMS key.
	// Only use `kms_key_name` if the location of the KMS key matches the database
	// instance's configuration (location) exactly. For example, if the KMS
	// location is in `us-central1` or `nam3`, then the database instance must also
	// be in `us-central1` or `nam3`. The Cloud KMS key that is used to encrypt and
	// decrypt the restored database. Set this field only when encryption_type is
	// `CUSTOMER_MANAGED_ENCRYPTION`. Values are of the form
	// `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{kms_
	// key_name}`.
	KmsKeyName string `json:"kmsKeyName,omitempty"`
	// KmsKeyNames: Optional. Specifies the KMS configuration for the one or more
	// keys used to protect the backup. Values are of the form
	// `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{kms_
	// key_name}`. The keys referenced by `kms_key_names` must fully cover all
	// regions of the backup's instance configuration. Some examples: * For
	// regional (single-region) instance configurations, specify a regional
	// location KMS key. * For multi-region instance configurations of type
	// `GOOGLE_MANAGED`, either specify a multi-region location KMS key or multiple
	// regional location KMS keys that cover all regions in the instance
	// configuration. * For an instance configuration of type `USER_MANAGED`,
	// specify only regional location KMS keys to cover each region in the instance
	// configuration. Multi-region location KMS keys aren't supported for
	// `USER_MANAGED` type instance configurations.
	KmsKeyNames []string `json:"kmsKeyNames,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EncryptionType") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EncryptionType") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateBackupEncryptionConfig) MarshalJSON() ([]byte, error) {
	type NoMethod CreateBackupEncryptionConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateBackupMetadata: Metadata type for the operation returned by
// CreateBackup.
type CreateBackupMetadata struct {
	// CancelTime: The time at which cancellation of this operation was received.
	// Operations.CancelOperation starts asynchronous cancellation on a
	// long-running operation. The server makes a best effort to cancel the
	// operation, but success is not guaranteed. Clients can use
	// Operations.GetOperation or other methods to check whether the cancellation
	// succeeded or whether the operation completed despite cancellation. On
	// successful cancellation, the operation is not deleted; instead, it becomes
	// an operation with an Operation.error value with a google.rpc.Status.code of
	// 1, corresponding to `Code.CANCELLED`.
	CancelTime string `json:"cancelTime,omitempty"`
	// Database: The name of the database the backup is created from.
	Database string `json:"database,omitempty"`
	// Name: The name of the backup being created.
	Name string `json:"name,omitempty"`
	// Progress: The progress of the CreateBackup operation.
	Progress *OperationProgress `json:"progress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateBackupMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CreateBackupMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateDatabaseMetadata: Metadata type for the operation returned by
// CreateDatabase.
type CreateDatabaseMetadata struct {
	// Database: The database being created.
	Database string `json:"database,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Database") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Database") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateDatabaseMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CreateDatabaseMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateDatabaseRequest: The request for CreateDatabase.
type CreateDatabaseRequest struct {
	// CreateStatement: Required. A `CREATE DATABASE` statement, which specifies
	// the ID of the new database. The database ID must conform to the regular
	// expression `a-z*[a-z0-9]` and be between 2 and 30 characters in length. If
	// the database ID is a reserved word or if it contains a hyphen, the database
	// ID must be enclosed in backticks (`` ` ``).
	CreateStatement string `json:"createStatement,omitempty"`
	// DatabaseDialect: Optional. The dialect of the Cloud Spanner Database.
	//
	// Possible values:
	//   "DATABASE_DIALECT_UNSPECIFIED" - Default value. This value will create a
	// database with the GOOGLE_STANDARD_SQL dialect.
	//   "GOOGLE_STANDARD_SQL" - GoogleSQL supported SQL.
	//   "POSTGRESQL" - PostgreSQL supported SQL.
	DatabaseDialect string `json:"databaseDialect,omitempty"`
	// EncryptionConfig: Optional. The encryption configuration for the database.
	// If this field is not specified, Cloud Spanner will encrypt/decrypt all data
	// at rest using Google default encryption.
	EncryptionConfig *EncryptionConfig `json:"encryptionConfig,omitempty"`
	// ExtraStatements: Optional. A list of DDL statements to run inside the newly
	// created database. Statements can create tables, indexes, etc. These
	// statements execute atomically with the creation of the database: if there is
	// an error in any statement, the database is not created.
	ExtraStatements []string `json:"extraStatements,omitempty"`
	// ProtoDescriptors: Optional. Proto descriptors used by `CREATE/ALTER PROTO
	// BUNDLE` statements in 'extra_statements'. Contains a protobuf-serialized
	// `google.protobuf.FileDescriptorSet`
	// (https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto)
	// descriptor set. To generate it, install
	// (https://grpc.io/docs/protoc-installation/) and run `protoc` with
	// --include_imports and --descriptor_set_out. For example, to generate for
	// moon/shot/app.proto, run ``` $protoc --proto_path=/app_path
	// --proto_path=/lib_path \ --include_imports \
	// --descriptor_set_out=descriptors.data \ moon/shot/app.proto ``` For more
	// details, see protobuffer self description
	// (https://developers.google.com/protocol-buffers/docs/techniques#self-description).
	ProtoDescriptors string `json:"protoDescriptors,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CreateStatement") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CreateStatement") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateDatabaseRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateDatabaseRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateInstanceConfigMetadata: Metadata type for the operation returned by
// CreateInstanceConfig.
type CreateInstanceConfigMetadata struct {
	// CancelTime: The time at which this operation was cancelled.
	CancelTime string `json:"cancelTime,omitempty"`
	// InstanceConfig: The target instance configuration end state.
	InstanceConfig *InstanceConfig `json:"instanceConfig,omitempty"`
	// Progress: The progress of the CreateInstanceConfig operation.
	Progress *InstanceOperationProgress `json:"progress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateInstanceConfigMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CreateInstanceConfigMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateInstanceConfigRequest: The request for CreateInstanceConfig.
type CreateInstanceConfigRequest struct {
	// InstanceConfig: Required. The `InstanceConfig` proto of the configuration to
	// create. `instance_config.name` must be `/instanceConfigs/`.
	// `instance_config.base_config` must be a Google-managed configuration name,
	// e.g. /instanceConfigs/us-east1, /instanceConfigs/nam3.
	InstanceConfig *InstanceConfig `json:"instanceConfig,omitempty"`
	// InstanceConfigId: Required. The ID of the instance configuration to create.
	// Valid identifiers are of the form `custom-[-a-z0-9]*[a-z0-9]` and must be
	// between 2 and 64 characters in length. The `custom-` prefix is required to
	// avoid name conflicts with Google-managed configurations.
	InstanceConfigId string `json:"instanceConfigId,omitempty"`
	// ValidateOnly: An option to validate, but not actually execute, a request,
	// and provide the same response.
	ValidateOnly bool `json:"validateOnly,omitempty"`
	// ForceSendFields is a list of field names (e.g. "InstanceConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "InstanceConfig") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateInstanceConfigRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateInstanceConfigRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateInstanceMetadata: Metadata type for the operation returned by
// CreateInstance.
type CreateInstanceMetadata struct {
	// CancelTime: The time at which this operation was cancelled. If set, this
	// operation is in the process of undoing itself (which is guaranteed to
	// succeed) and cannot be cancelled again.
	CancelTime string `json:"cancelTime,omitempty"`
	// EndTime: The time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// ExpectedFulfillmentPeriod: The expected fulfillment period of this create
	// operation.
	//
	// Possible values:
	//   "FULFILLMENT_PERIOD_UNSPECIFIED" - Not specified.
	//   "FULFILLMENT_PERIOD_NORMAL" - Normal fulfillment period. The operation is
	// expected to complete within minutes.
	//   "FULFILLMENT_PERIOD_EXTENDED" - Extended fulfillment period. It can take
	// up to an hour for the operation to complete.
	ExpectedFulfillmentPeriod string `json:"expectedFulfillmentPeriod,omitempty"`
	// Instance: The instance being created.
	Instance *Instance `json:"instance,omitempty"`
	// StartTime: The time at which the CreateInstance request was received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateInstanceMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CreateInstanceMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateInstancePartitionMetadata: Metadata type for the operation returned by
// CreateInstancePartition.
type CreateInstancePartitionMetadata struct {
	// CancelTime: The time at which this operation was cancelled. If set, this
	// operation is in the process of undoing itself (which is guaranteed to
	// succeed) and cannot be cancelled again.
	CancelTime string `json:"cancelTime,omitempty"`
	// EndTime: The time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// InstancePartition: The instance partition being created.
	InstancePartition *InstancePartition `json:"instancePartition,omitempty"`
	// StartTime: The time at which the CreateInstancePartition request was
	// received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateInstancePartitionMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod CreateInstancePartitionMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateInstancePartitionRequest: The request for CreateInstancePartition.
type CreateInstancePartitionRequest struct {
	// InstancePartition: Required. The instance partition to create. The
	// instance_partition.name may be omitted, but if specified must be
	// `/instancePartitions/`.
	InstancePartition *InstancePartition `json:"instancePartition,omitempty"`
	// InstancePartitionId: Required. The ID of the instance partition to create.
	// Valid identifiers are of the form `a-z*[a-z0-9]` and must be between 2 and
	// 64 characters in length.
	InstancePartitionId string `json:"instancePartitionId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "InstancePartition") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "InstancePartition") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateInstancePartitionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateInstancePartitionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateInstanceRequest: The request for CreateInstance.
type CreateInstanceRequest struct {
	// Instance: Required. The instance to create. The name may be omitted, but if
	// specified must be `/instances/`.
	Instance *Instance `json:"instance,omitempty"`
	// InstanceId: Required. The ID of the instance to create. Valid identifiers
	// are of the form `a-z*[a-z0-9]` and must be between 2 and 64 characters in
	// length.
	InstanceId string `json:"instanceId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Instance") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Instance") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateInstanceRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateInstanceRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CreateSessionRequest: The request for CreateSession.
type CreateSessionRequest struct {
	// Session: Required. The session to create.
	Session *Session `json:"session,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Session") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Session") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CreateSessionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod CreateSessionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// CrontabSpec: CrontabSpec can be used to specify the version time and
// frequency at which the backup is created.
type CrontabSpec struct {
	// CreationWindow: Output only. Scheduled backups contain an externally
	// consistent copy of the database at the version time specified in
	// `schedule_spec.cron_spec`. However, Spanner might not initiate the creation
	// of the scheduled backups at that version time. Spanner initiates the
	// creation of scheduled backups within the time window bounded by the
	// version_time specified in `schedule_spec.cron_spec` and version_time +
	// `creation_window`.
	CreationWindow string `json:"creationWindow,omitempty"`
	// Text: Required. Textual representation of the crontab. User can customize
	// the backup frequency and the backup version time using the cron expression.
	// The version time must be in UTC timezone. The backup will contain an
	// externally consistent copy of the database at the version time. Full backups
	// must be scheduled a minimum of 12 hours apart and incremental backups must
	// be scheduled a minimum of 4 hours apart. Examples of valid cron
	// specifications: * `0 2/12 * * *` : every 12 hours at (2, 14) hours past
	// midnight in UTC. * `0 2,14 * * *` : every 12 hours at (2, 14) hours past
	// midnight in UTC. * `0 */4 * * *` : (incremental backups only) every 4 hours
	// at (0, 4, 8, 12, 16, 20) hours past midnight in UTC. * `0 2 * * *` : once a
	// day at 2 past midnight in UTC. * `0 2 * * 0` : once a week every Sunday at 2
	// past midnight in UTC. * `0 2 8 * *` : once a month on 8th day at 2 past
	// midnight in UTC.
	Text string `json:"text,omitempty"`
	// TimeZone: Output only. The time zone of the times in `CrontabSpec.text`.
	// Currently, only UTC is supported.
	TimeZone string `json:"timeZone,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CreationWindow") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CreationWindow") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s CrontabSpec) MarshalJSON() ([]byte, error) {
	type NoMethod CrontabSpec
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DataChangeRecord: A data change record contains a set of changes to a table
// with the same modification type (insert, update, or delete) committed at the
// same commit timestamp in one change stream partition for the same
// transaction. Multiple data change records can be returned for the same
// transaction across multiple change stream partitions.
type DataChangeRecord struct {
	// ColumnMetadata: Provides metadata describing the columns associated with the
	// mods listed below.
	ColumnMetadata []*ColumnMetadata `json:"columnMetadata,omitempty"`
	// CommitTimestamp: Indicates the timestamp in which the change was committed.
	// DataChangeRecord.commit_timestamps, PartitionStartRecord.start_timestamps,
	// PartitionEventRecord.commit_timestamps, and
	// PartitionEndRecord.end_timestamps can have the same value in the same
	// partition.
	CommitTimestamp string `json:"commitTimestamp,omitempty"`
	// IsLastRecordInTransactionInPartition: Indicates whether this is the last
	// record for a transaction in the current partition. Clients can use this
	// field to determine when all records for a transaction in the current
	// partition have been received.
	IsLastRecordInTransactionInPartition bool `json:"isLastRecordInTransactionInPartition,omitempty"`
	// IsSystemTransaction: Indicates whether the transaction is a system
	// transaction. System transactions include those issued by time-to-live (TTL),
	// column backfill, etc.
	IsSystemTransaction bool `json:"isSystemTransaction,omitempty"`
	// ModType: Describes the type of change.
	//
	// Possible values:
	//   "MOD_TYPE_UNSPECIFIED" - Not specified.
	//   "INSERT" - Indicates data was inserted.
	//   "UPDATE" - Indicates existing data was updated.
	//   "DELETE" - Indicates existing data was deleted.
	ModType string `json:"modType,omitempty"`
	// Mods: Describes the changes that were made.
	Mods []*Mod `json:"mods,omitempty"`
	// NumberOfPartitionsInTransaction: Indicates the number of partitions that
	// return data change records for this transaction. This value can be helpful
	// in assembling all records associated with a particular transaction.
	NumberOfPartitionsInTransaction int64 `json:"numberOfPartitionsInTransaction,omitempty"`
	// NumberOfRecordsInTransaction: Indicates the number of data change records
	// that are part of this transaction across all change stream partitions. This
	// value can be used to assemble all the records associated with a particular
	// transaction.
	NumberOfRecordsInTransaction int64 `json:"numberOfRecordsInTransaction,omitempty"`
	// RecordSequence: Record sequence numbers are unique and monotonically
	// increasing (but not necessarily contiguous) for a specific timestamp across
	// record types in the same partition. To guarantee ordered processing, the
	// reader should process records (of potentially different types) in
	// record_sequence order for a specific timestamp in the same partition. The
	// record sequence number ordering across partitions is only meaningful in the
	// context of a specific transaction. Record sequence numbers are unique across
	// partitions for a specific transaction. Sort the DataChangeRecords for the
	// same server_transaction_id by record_sequence to reconstruct the ordering of
	// the changes within the transaction.
	RecordSequence string `json:"recordSequence,omitempty"`
	// ServerTransactionId: Provides a globally unique string that represents the
	// transaction in which the change was committed. Multiple transactions can
	// have the same commit timestamp, but each transaction has a unique
	// server_transaction_id.
	ServerTransactionId string `json:"serverTransactionId,omitempty"`
	// Table: Name of the table affected by the change.
	Table string `json:"table,omitempty"`
	// TransactionTag: Indicates the transaction tag associated with this
	// transaction.
	TransactionTag string `json:"transactionTag,omitempty"`
	// ValueCaptureType: Describes the value capture type that was specified in the
	// change stream configuration when this change was captured.
	//
	// Possible values:
	//   "VALUE_CAPTURE_TYPE_UNSPECIFIED" - Not specified.
	//   "OLD_AND_NEW_VALUES" - Records both old and new values of the modified
	// watched columns.
	//   "NEW_VALUES" - Records only new values of the modified watched columns.
	//   "NEW_ROW" - Records new values of all watched columns, including modified
	// and unmodified columns.
	//   "NEW_ROW_AND_OLD_VALUES" - Records the new values of all watched columns,
	// including modified and unmodified columns. Also records the old values of
	// the modified columns.
	ValueCaptureType string `json:"valueCaptureType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ColumnMetadata") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ColumnMetadata") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DataChangeRecord) MarshalJSON() ([]byte, error) {
	type NoMethod DataChangeRecord
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Database: A Cloud Spanner database.
type Database struct {
	// CreateTime: Output only. If exists, the time at which the database creation
	// started.
	CreateTime string `json:"createTime,omitempty"`
	// DatabaseDialect: Output only. The dialect of the Cloud Spanner Database.
	//
	// Possible values:
	//   "DATABASE_DIALECT_UNSPECIFIED" - Default value. This value will create a
	// database with the GOOGLE_STANDARD_SQL dialect.
	//   "GOOGLE_STANDARD_SQL" - GoogleSQL supported SQL.
	//   "POSTGRESQL" - PostgreSQL supported SQL.
	DatabaseDialect string `json:"databaseDialect,omitempty"`
	// DefaultLeader: Output only. The read-write region which contains the
	// database's leader replicas. This is the same as the value of default_leader
	// database option set using DatabaseAdmin.CreateDatabase or
	// DatabaseAdmin.UpdateDatabaseDdl. If not explicitly set, this is empty.
	DefaultLeader string `json:"defaultLeader,omitempty"`
	// EarliestVersionTime: Output only. Earliest timestamp at which older versions
	// of the data can be read. This value is continuously updated by Cloud Spanner
	// and becomes stale the moment it is queried. If you are using this value to
	// recover data, make sure to account for the time from the moment when the
	// value is queried to the moment when you initiate the recovery.
	EarliestVersionTime string `json:"earliestVersionTime,omitempty"`
	// EnableDropProtection: Optional. Whether drop protection is enabled for this
	// database. Defaults to false, if not set. For more details, please see how to
	// prevent accidental database deletion
	// (https://cloud.google.com/spanner/docs/prevent-database-deletion).
	EnableDropProtection bool `json:"enableDropProtection,omitempty"`
	// EncryptionConfig: Output only. For databases that are using customer managed
	// encryption, this field contains the encryption configuration for the
	// database. For databases that are using Google default or other types of
	// encryption, this field is empty.
	EncryptionConfig *EncryptionConfig `json:"encryptionConfig,omitempty"`
	// EncryptionInfo: Output only. For databases that are using customer managed
	// encryption, this field contains the encryption information for the database,
	// such as all Cloud KMS key versions that are in use. The `encryption_status`
	// field inside of each `EncryptionInfo` is not populated. For databases that
	// are using Google default or other types of encryption, this field is empty.
	// This field is propagated lazily from the backend. There might be a delay
	// from when a key version is being used and when it appears in this field.
	EncryptionInfo []*EncryptionInfo `json:"encryptionInfo,omitempty"`
	// Name: Required. The name of the database. Values are of the form
	// `projects//instances//databases/`, where `` is as specified in the `CREATE
	// DATABASE` statement. This name can be passed to other API methods to
	// identify the database.
	Name string `json:"name,omitempty"`
	// QuorumInfo: Output only. Applicable only for databases that use dual-region
	// instance configurations. Contains information about the quorum.
	QuorumInfo *QuorumInfo `json:"quorumInfo,omitempty"`
	// Reconciling: Output only. If true, the database is being updated. If false,
	// there are no ongoing update operations for the database.
	Reconciling bool `json:"reconciling,omitempty"`
	// RestoreInfo: Output only. Applicable only for restored databases. Contains
	// information about the restore source.
	RestoreInfo *RestoreInfo `json:"restoreInfo,omitempty"`
	// State: Output only. The current database state.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Not specified.
	//   "CREATING" - The database is still being created. Operations on the
	// database may fail with `FAILED_PRECONDITION` in this state.
	//   "READY" - The database is fully created and ready for use.
	//   "READY_OPTIMIZING" - The database is fully created and ready for use, but
	// is still being optimized for performance and cannot handle full load. In
	// this state, the database still references the backup it was restore from,
	// preventing the backup from being deleted. When optimizations are complete,
	// the full performance of the database will be restored, and the database will
	// transition to `READY` state.
	State string `json:"state,omitempty"`
	// VersionRetentionPeriod: Output only. The period in which Cloud Spanner
	// retains all versions of data for the database. This is the same as the value
	// of version_retention_period database option set using UpdateDatabaseDdl.
	// Defaults to 1 hour, if not set.
	VersionRetentionPeriod string `json:"versionRetentionPeriod,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "CreateTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CreateTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Database) MarshalJSON() ([]byte, error) {
	type NoMethod Database
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DatabaseMoveConfig: The configuration for each database in the target
// instance configuration.
type DatabaseMoveConfig struct {
	// DatabaseId: Required. The unique identifier of the database resource in the
	// Instance. For example, if the database uri is
	// `projects/foo/instances/bar/databases/baz`, then the id to supply here is
	// baz.
	DatabaseId string `json:"databaseId,omitempty"`
	// EncryptionConfig: Optional. Encryption configuration to be used for the
	// database in the target configuration. The encryption configuration must be
	// specified for every database which currently uses CMEK encryption. If a
	// database currently uses Google-managed encryption and a target encryption
	// configuration is not specified, then the database defaults to Google-managed
	// encryption. If a database currently uses Google-managed encryption and a
	// target CMEK encryption is specified, the request is rejected. If a database
	// currently uses CMEK encryption, then a target encryption configuration must
	// be specified. You can't move a CMEK database to a Google-managed encryption
	// database using the MoveInstance API.
	EncryptionConfig *InstanceEncryptionConfig `json:"encryptionConfig,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DatabaseId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DatabaseId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DatabaseMoveConfig) MarshalJSON() ([]byte, error) {
	type NoMethod DatabaseMoveConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DatabaseRole: A Cloud Spanner database role.
type DatabaseRole struct {
	// Name: Required. The name of the database role. Values are of the form
	// `projects//instances//databases//databaseRoles/` where `` is as specified in
	// the `CREATE ROLE` DDL statement.
	Name string `json:"name,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Name") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Name") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DatabaseRole) MarshalJSON() ([]byte, error) {
	type NoMethod DatabaseRole
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DdlStatementActionInfo: Action information extracted from a DDL statement.
// This proto is used to display the brief info of the DDL statement for the
// operation UpdateDatabaseDdl.
type DdlStatementActionInfo struct {
	// Action: The action for the DDL statement, for example, CREATE, ALTER, DROP,
	// GRANT, etc. This field is a non-empty string.
	Action string `json:"action,omitempty"`
	// EntityNames: The entity names being operated on the DDL statement. For
	// example, 1. For statement "CREATE TABLE t1(...)", `entity_names` = ["t1"].
	// 2. For statement "GRANT ROLE r1, r2 ...", `entity_names` = ["r1", "r2"]. 3.
	// For statement "ANALYZE", `entity_names` = [].
	EntityNames []string `json:"entityNames,omitempty"`
	// EntityType: The entity type for the DDL statement, for example, TABLE,
	// INDEX, VIEW, etc. This field can be empty string for some DDL statement, for
	// example, for statement "ANALYZE", `entity_type` = "".
	EntityType string `json:"entityType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Action") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Action") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DdlStatementActionInfo) MarshalJSON() ([]byte, error) {
	type NoMethod DdlStatementActionInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Delete: Arguments to delete operations.
type Delete struct {
	// KeySet: Required. The primary keys of the rows within table to delete. The
	// primary keys must be specified in the order in which they appear in the
	// `PRIMARY KEY()` clause of the table's equivalent DDL statement (the DDL
	// statement used to create the table). Delete is idempotent. The transaction
	// will succeed even if some or all rows do not exist.
	KeySet *KeySet `json:"keySet,omitempty"`
	// Table: Required. The table whose rows will be deleted.
	Table string `json:"table,omitempty"`
	// ForceSendFields is a list of field names (e.g. "KeySet") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "KeySet") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Delete) MarshalJSON() ([]byte, error) {
	type NoMethod Delete
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DerivedMetric: A message representing a derived metric.
type DerivedMetric struct {
	// Denominator: The name of the denominator metric. e.g. "rows".
	Denominator *LocalizedString `json:"denominator,omitempty"`
	// Numerator: The name of the numerator metric. e.g. "latency".
	Numerator *LocalizedString `json:"numerator,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Denominator") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Denominator") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DerivedMetric) MarshalJSON() ([]byte, error) {
	type NoMethod DerivedMetric
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DiagnosticMessage: A message representing the key visualizer diagnostic
// messages.
type DiagnosticMessage struct {
	// Info: Information about this diagnostic information.
	Info *LocalizedString `json:"info,omitempty"`
	// Metric: The metric.
	Metric *LocalizedString `json:"metric,omitempty"`
	// MetricSpecific: Whether this message is specific only for the current
	// metric. By default Diagnostics are shown for all metrics, regardless which
	// metric is the currently selected metric in the UI. However occasionally a
	// metric will generate so many messages that the resulting visual clutter
	// becomes overwhelming. In this case setting this to true, will show the
	// diagnostic messages for that metric only if it is the currently selected
	// metric.
	MetricSpecific bool `json:"metricSpecific,omitempty"`
	// Severity: The severity of the diagnostic message.
	//
	// Possible values:
	//   "SEVERITY_UNSPECIFIED" - Required default value.
	//   "INFO" - Lowest severity level "Info".
	//   "WARNING" - Middle severity level "Warning".
	//   "ERROR" - Severity level signaling an error "Error"
	//   "FATAL" - Severity level signaling a non recoverable error "Fatal"
	Severity string `json:"severity,omitempty"`
	// ShortMessage: The short message.
	ShortMessage *LocalizedString `json:"shortMessage,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Info") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Info") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DiagnosticMessage) MarshalJSON() ([]byte, error) {
	type NoMethod DiagnosticMessage
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DirectedReadOptions: The `DirectedReadOptions` can be used to indicate which
// replicas or regions should be used for non-transactional reads or queries.
// `DirectedReadOptions` can only be specified for a read-only transaction,
// otherwise the API returns an `INVALID_ARGUMENT` error.
type DirectedReadOptions struct {
	// ExcludeReplicas: `Exclude_replicas` indicates that specified replicas should
	// be excluded from serving requests. Spanner doesn't route requests to the
	// replicas in this list.
	ExcludeReplicas *ExcludeReplicas `json:"excludeReplicas,omitempty"`
	// IncludeReplicas: `Include_replicas` indicates the order of replicas (as they
	// appear in this list) to process the request. If `auto_failover_disabled` is
	// set to `true` and all replicas are exhausted without finding a healthy
	// replica, Spanner waits for a replica in the list to become available,
	// requests might fail due to `DEADLINE_EXCEEDED` errors.
	IncludeReplicas *IncludeReplicas `json:"includeReplicas,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExcludeReplicas") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExcludeReplicas") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s DirectedReadOptions) MarshalJSON() ([]byte, error) {
	type NoMethod DirectedReadOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// DualRegionQuorum: Message type for a dual-region quorum. Currently this type
// has no options.
type DualRegionQuorum struct {
}

// Empty: A generic empty message that you can re-use to avoid defining
// duplicated empty messages in your APIs. A typical example is to use it as
// the request or the response type of an API method. For instance: service Foo
// { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }
type Empty struct {
	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
}

// EncryptionConfig: Encryption configuration for a Cloud Spanner database.
type EncryptionConfig struct {
	// KmsKeyName: The Cloud KMS key to be used for encrypting and decrypting the
	// database. Values are of the form
	// `projects//locations//keyRings//cryptoKeys/`.
	KmsKeyName string `json:"kmsKeyName,omitempty"`
	// KmsKeyNames: Specifies the KMS configuration for one or more keys used to
	// encrypt the database. Values are of the form
	// `projects//locations//keyRings//cryptoKeys/`. The keys referenced by
	// `kms_key_names` must fully cover all regions of the database's instance
	// configuration. Some examples: * For regional (single-region) instance
	// configurations, specify a regional location KMS key. * For multi-region
	// instance configurations of type `GOOGLE_MANAGED`, either specify a
	// multi-region location KMS key or multiple regional location KMS keys that
	// cover all regions in the instance configuration. * For an instance
	// configuration of type `USER_MANAGED`, specify only regional location KMS
	// keys to cover each region in the instance configuration. Multi-region
	// location KMS keys aren't supported for `USER_MANAGED` type instance
	// configurations.
	KmsKeyNames []string `json:"kmsKeyNames,omitempty"`
	// ForceSendFields is a list of field names (e.g. "KmsKeyName") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "KmsKeyName") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s EncryptionConfig) MarshalJSON() ([]byte, error) {
	type NoMethod EncryptionConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// EncryptionInfo: Encryption information for a Cloud Spanner database or
// backup.
type EncryptionInfo struct {
	// EncryptionStatus: Output only. If present, the status of a recent
	// encrypt/decrypt call on underlying data for this database or backup.
	// Regardless of status, data is always encrypted at rest.
	EncryptionStatus *Status `json:"encryptionStatus,omitempty"`
	// EncryptionType: Output only. The type of encryption.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Encryption type was not specified, though data at
	// rest remains encrypted.
	//   "GOOGLE_DEFAULT_ENCRYPTION" - The data is encrypted at rest with a key
	// that is fully managed by Google. No key version or status will be populated.
	// This is the default state.
	//   "CUSTOMER_MANAGED_ENCRYPTION" - The data is encrypted at rest with a key
	// that is managed by the customer. The active version of the key.
	// `kms_key_version` will be populated, and `encryption_status` may be
	// populated.
	EncryptionType string `json:"encryptionType,omitempty"`
	// KmsKeyVersion: Output only. A Cloud KMS key version that is being used to
	// protect the database or backup.
	KmsKeyVersion string `json:"kmsKeyVersion,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EncryptionStatus") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EncryptionStatus") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s EncryptionInfo) MarshalJSON() ([]byte, error) {
	type NoMethod EncryptionInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ExcludeReplicas: An ExcludeReplicas contains a repeated set of
// ReplicaSelection that should be excluded from serving requests.
type ExcludeReplicas struct {
	// ReplicaSelections: The directed read replica selector.
	ReplicaSelections []*ReplicaSelection `json:"replicaSelections,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ReplicaSelections") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ReplicaSelections") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ExcludeReplicas) MarshalJSON() ([]byte, error) {
	type NoMethod ExcludeReplicas
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ExecuteBatchDmlRequest: The request for ExecuteBatchDml.
type ExecuteBatchDmlRequest struct {
	// LastStatements: Optional. If set to `true`, this request marks the end of
	// the transaction. After these statements execute, you must commit or abort
	// the transaction. Attempts to execute any other requests against this
	// transaction (including reads and queries) are rejected. Setting this option
	// might cause some error reporting to be deferred until commit time (for
	// example, validation of unique constraints). Given this, successful execution
	// of statements shouldn't be assumed until a subsequent `Commit` call
	// completes successfully.
	LastStatements bool `json:"lastStatements,omitempty"`
	// RequestOptions: Common options for this request.
	RequestOptions *RequestOptions `json:"requestOptions,omitempty"`
	// Seqno: Required. A per-transaction sequence number used to identify this
	// request. This field makes each request idempotent such that if the request
	// is received multiple times, at most one succeeds. The sequence number must
	// be monotonically increasing within the transaction. If a request arrives for
	// the first time with an out-of-order sequence number, the transaction might
	// be aborted. Replays of previously handled requests yield the same response
	// as the first execution.
	Seqno int64 `json:"seqno,omitempty,string"`
	// Statements: Required. The list of statements to execute in this batch.
	// Statements are executed serially, such that the effects of statement `i` are
	// visible to statement `i+1`. Each statement must be a DML statement.
	// Execution stops at the first failed statement; the remaining statements are
	// not executed. Callers must provide at least one statement.
	Statements []*Statement `json:"statements,omitempty"`
	// Transaction: Required. The transaction to use. Must be a read-write
	// transaction. To protect against replays, single-use transactions are not
	// supported. The caller must either supply an existing transaction ID or begin
	// a new transaction.
	Transaction *TransactionSelector `json:"transaction,omitempty"`
	// ForceSendFields is a list of field names (e.g. "LastStatements") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "LastStatements") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ExecuteBatchDmlRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ExecuteBatchDmlRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ExecuteBatchDmlResponse: The response for ExecuteBatchDml. Contains a list
// of ResultSet messages, one for each DML statement that has successfully
// executed, in the same order as the statements in the request. If a statement
// fails, the status in the response body identifies the cause of the failure.
// To check for DML statements that failed, use the following approach: 1.
// Check the status in the response message. The google.rpc.Code enum value
// `OK` indicates that all statements were executed successfully. 2. If the
// status was not `OK`, check the number of result sets in the response. If the
// response contains `N` ResultSet messages, then statement `N+1` in the
// request failed. Example 1: * Request: 5 DML statements, all executed
// successfully. * Response: 5 ResultSet messages, with the status `OK`.
// Example 2: * Request: 5 DML statements. The third statement has a syntax
// error. * Response: 2 ResultSet messages, and a syntax error
// (`INVALID_ARGUMENT`) status. The number of ResultSet messages indicates that
// the third statement failed, and the fourth and fifth statements were not
// executed.
type ExecuteBatchDmlResponse struct {
	// PrecommitToken: Optional. A precommit token is included if the read-write
	// transaction is on a multiplexed session. Pass the precommit token with the
	// highest sequence number from this transaction attempt should be passed to
	// the Commit request for this transaction.
	PrecommitToken *MultiplexedSessionPrecommitToken `json:"precommitToken,omitempty"`
	// ResultSets: One ResultSet for each statement in the request that ran
	// successfully, in the same order as the statements in the request. Each
	// ResultSet does not contain any rows. The ResultSetStats in each ResultSet
	// contain the number of rows modified by the statement. Only the first
	// ResultSet in the response contains valid ResultSetMetadata.
	ResultSets []*ResultSet `json:"resultSets,omitempty"`
	// Status: If all DML statements are executed successfully, the status is `OK`.
	// Otherwise, the error status of the first failed statement.
	Status *Status `json:"status,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "PrecommitToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "PrecommitToken") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ExecuteBatchDmlResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ExecuteBatchDmlResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ExecuteSqlRequest: The request for ExecuteSql and ExecuteStreamingSql.
type ExecuteSqlRequest struct {
	// DataBoostEnabled: If this is for a partitioned query and this field is set
	// to `true`, the request is executed with Spanner Data Boost independent
	// compute resources. If the field is set to `true` but the request doesn't set
	// `partition_token`, the API returns an `INVALID_ARGUMENT` error.
	DataBoostEnabled bool `json:"dataBoostEnabled,omitempty"`
	// DirectedReadOptions: Directed read options for this request.
	DirectedReadOptions *DirectedReadOptions `json:"directedReadOptions,omitempty"`
	// LastStatement: Optional. If set to `true`, this statement marks the end of
	// the transaction. After this statement executes, you must commit or abort the
	// transaction. Attempts to execute any other requests against this transaction
	// (including reads and queries) are rejected. For DML statements, setting this
	// option might cause some error reporting to be deferred until commit time
	// (for example, validation of unique constraints). Given this, successful
	// execution of a DML statement shouldn't be assumed until a subsequent
	// `Commit` call completes successfully.
	LastStatement bool `json:"lastStatement,omitempty"`
	// ParamTypes: It isn't always possible for Cloud Spanner to infer the right
	// SQL type from a JSON value. For example, values of type `BYTES` and values
	// of type `STRING` both appear in params as JSON strings. In these cases, you
	// can use `param_types` to specify the exact SQL type for some or all of the
	// SQL statement parameters. See the definition of Type for more information
	// about SQL types.
	ParamTypes map[string]Type `json:"paramTypes,omitempty"`
	// Params: Parameter names and values that bind to placeholders in the SQL
	// string. A parameter placeholder consists of the `@` character followed by
	// the parameter name (for example, `@firstName`). Parameter names must conform
	// to the naming requirements of identifiers as specified at
	// https://cloud.google.com/spanner/docs/lexical#identifiers. Parameters can
	// appear anywhere that a literal value is expected. The same parameter name
	// can be used more than once, for example: "WHERE id > @msg_id AND id <
	// @msg_id + 100" It's an error to execute a SQL statement with unbound
	// parameters.
	Params googleapi.RawMessage `json:"params,omitempty"`
	// PartitionToken: If present, results are restricted to the specified
	// partition previously created using `PartitionQuery`. There must be an exact
	// match for the values of fields common to this message and the
	// `PartitionQueryRequest` message used to create this `partition_token`.
	PartitionToken string `json:"partitionToken,omitempty"`
	// QueryMode: Used to control the amount of debugging information returned in
	// ResultSetStats. If partition_token is set, query_mode can only be set to
	// QueryMode.NORMAL.
	//
	// Possible values:
	//   "NORMAL" - The default mode. Only the statement results are returned.
	//   "PLAN" - This mode returns only the query plan, without any results or
	// execution statistics information.
	//   "PROFILE" - This mode returns the query plan, overall execution
	// statistics, operator level execution statistics along with the results. This
	// has a performance overhead compared to the other modes. It isn't recommended
	// to use this mode for production traffic.
	//   "WITH_STATS" - This mode returns the overall (but not operator-level)
	// execution statistics along with the results.
	//   "WITH_PLAN_AND_STATS" - This mode returns the query plan, overall (but not
	// operator-level) execution statistics along with the results.
	QueryMode string `json:"queryMode,omitempty"`
	// QueryOptions: Query optimizer configuration to use for the given query.
	QueryOptions *QueryOptions `json:"queryOptions,omitempty"`
	// RequestOptions: Common options for this request.
	RequestOptions *RequestOptions `json:"requestOptions,omitempty"`
	// ResumeToken: If this request is resuming a previously interrupted SQL
	// statement execution, `resume_token` should be copied from the last
	// PartialResultSet yielded before the interruption. Doing this enables the new
	// SQL statement execution to resume where the last one left off. The rest of
	// the request parameters must exactly match the request that yielded this
	// token.
	ResumeToken string `json:"resumeToken,omitempty"`
	// Seqno: A per-transaction sequence number used to identify this request. This
	// field makes each request idempotent such that if the request is received
	// multiple times, at most one succeeds. The sequence number must be
	// monotonically increasing within the transaction. If a request arrives for
	// the first time with an out-of-order sequence number, the transaction can be
	// aborted. Replays of previously handled requests yield the same response as
	// the first execution. Required for DML statements. Ignored for queries.
	Seqno int64 `json:"seqno,omitempty,string"`
	// Sql: Required. The SQL string.
	Sql string `json:"sql,omitempty"`
	// Transaction: The transaction to use. For queries, if none is provided, the
	// default is a temporary read-only transaction with strong concurrency.
	// Standard DML statements require a read-write transaction. To protect against
	// replays, single-use transactions are not supported. The caller must either
	// supply an existing transaction ID or begin a new transaction. Partitioned
	// DML requires an existing Partitioned DML transaction ID.
	Transaction *TransactionSelector `json:"transaction,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DataBoostEnabled") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DataBoostEnabled") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ExecuteSqlRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ExecuteSqlRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Expr: Represents a textual expression in the Common Expression Language
// (CEL) syntax. CEL is a C-like expression language. The syntax and semantics
// of CEL are documented at https://github.com/google/cel-spec. Example
// (Comparison): title: "Summary size limit" description: "Determines if a
// summary is less than 100 chars" expression: "document.summary.size() < 100"
// Example (Equality): title: "Requestor is owner" description: "Determines if
// requestor is the document owner" expression: "document.owner ==
// request.auth.claims.email" Example (Logic): title: "Public documents"
// description: "Determine whether the document should be publicly visible"
// expression: "document.type != 'private' && document.type != 'internal'"
// Example (Data Manipulation): title: "Notification string" description:
// "Create a notification string with a timestamp." expression: "'New message
// received at ' + string(document.create_time)" The exact variables and
// functions that may be referenced within an expression are determined by the
// service that evaluates it. See the service documentation for additional
// information.
type Expr struct {
	// Description: Optional. Description of the expression. This is a longer text
	// which describes the expression, e.g. when hovered over it in a UI.
	Description string `json:"description,omitempty"`
	// Expression: Textual representation of an expression in Common Expression
	// Language syntax.
	Expression string `json:"expression,omitempty"`
	// Location: Optional. String indicating the location of the expression for
	// error reporting, e.g. a file name and a position in the file.
	Location string `json:"location,omitempty"`
	// Title: Optional. Title for the expression, i.e. a short string describing
	// its purpose. This can be used e.g. in UIs which allow to enter the
	// expression.
	Title string `json:"title,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Description") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Description") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Expr) MarshalJSON() ([]byte, error) {
	type NoMethod Expr
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Field: Message representing a single field of a struct.
type Field struct {
	// Name: The name of the field. For reads, this is the column name. For SQL
	// queries, it is the column alias (e.g., "Word" in the query "SELECT
	// 'hello' AS Word"), or the column name (e.g., "ColName" in the query
	// "SELECT ColName FROM Table"). Some columns might have an empty name (e.g.,
	// "SELECT UPPER(ColName)"). Note that a query result can contain multiple
	// fields with the same name.
	Name string `json:"name,omitempty"`
	// Type: The type of the field.
	Type *Type `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Name") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Name") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Field) MarshalJSON() ([]byte, error) {
	type NoMethod Field
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// FreeInstanceMetadata: Free instance specific metadata that is kept even
// after an instance has been upgraded for tracking purposes.
type FreeInstanceMetadata struct {
	// ExpireBehavior: Specifies the expiration behavior of a free instance. The
	// default of ExpireBehavior is `REMOVE_AFTER_GRACE_PERIOD`. This can be
	// modified during or after creation, and before expiration.
	//
	// Possible values:
	//   "EXPIRE_BEHAVIOR_UNSPECIFIED" - Not specified.
	//   "FREE_TO_PROVISIONED" - When the free instance expires, upgrade the
	// instance to a provisioned instance.
	//   "REMOVE_AFTER_GRACE_PERIOD" - When the free instance expires, disable the
	// instance, and delete it after the grace period passes if it has not been
	// upgraded.
	ExpireBehavior string `json:"expireBehavior,omitempty"`
	// ExpireTime: Output only. Timestamp after which the instance will either be
	// upgraded or scheduled for deletion after a grace period. ExpireBehavior is
	// used to choose between upgrading or scheduling the free instance for
	// deletion. This timestamp is set during the creation of a free instance.
	ExpireTime string `json:"expireTime,omitempty"`
	// UpgradeTime: Output only. If present, the timestamp at which the free
	// instance was upgraded to a provisioned instance.
	UpgradeTime string `json:"upgradeTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExpireBehavior") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExpireBehavior") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s FreeInstanceMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod FreeInstanceMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// FullBackupSpec: The specification for full backups. A full backup stores the
// entire contents of the database at a given version time.
type FullBackupSpec struct {
}

// GetDatabaseDdlResponse: The response for GetDatabaseDdl.
type GetDatabaseDdlResponse struct {
	// ProtoDescriptors: Proto descriptors stored in the database. Contains a
	// protobuf-serialized google.protobuf.FileDescriptorSet
	// (https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
	// For more details, see protobuffer self description
	// (https://developers.google.com/protocol-buffers/docs/techniques#self-description).
	ProtoDescriptors string `json:"protoDescriptors,omitempty"`
	// Statements: A list of formatted DDL statements defining the schema of the
	// database specified in the request.
	Statements []string `json:"statements,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ProtoDescriptors") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ProtoDescriptors") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GetDatabaseDdlResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GetDatabaseDdlResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GetIamPolicyRequest: Request message for `GetIamPolicy` method.
type GetIamPolicyRequest struct {
	// Options: OPTIONAL: A `GetPolicyOptions` object for specifying options to
	// `GetIamPolicy`.
	Options *GetPolicyOptions `json:"options,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Options") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Options") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GetIamPolicyRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GetIamPolicyRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// GetPolicyOptions: Encapsulates settings provided to GetIamPolicy.
type GetPolicyOptions struct {
	// RequestedPolicyVersion: Optional. The maximum policy version that will be
	// used to format the policy. Valid values are 0, 1, and 3. Requests specifying
	// an invalid value will be rejected. Requests for policies with any
	// conditional role bindings must specify version 3. Policies with no
	// conditional role bindings may specify any valid value or leave the field
	// unset. The policy in the response might use the policy version that you
	// specified, or it might use a lower policy version. For example, if you
	// specify version 3, but the policy has no conditional role bindings, the
	// response uses version 1. To learn which resources support conditions in
	// their IAM policies, see the IAM documentation
	// (https://cloud.google.com/iam/help/conditions/resource-policies).
	RequestedPolicyVersion int64 `json:"requestedPolicyVersion,omitempty"`
	// ForceSendFields is a list of field names (e.g. "RequestedPolicyVersion") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "RequestedPolicyVersion") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s GetPolicyOptions) MarshalJSON() ([]byte, error) {
	type NoMethod GetPolicyOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// HeartbeatRecord: A heartbeat record is returned as a progress indicator,
// when there are no data changes or any other partition record types in the
// change stream partition.
type HeartbeatRecord struct {
	// Timestamp: Indicates the timestamp at which the query has returned all the
	// records in the change stream partition with timestamp <= heartbeat
	// timestamp. The heartbeat timestamp will not be the same as the timestamps of
	// other record types in the same partition.
	Timestamp string `json:"timestamp,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Timestamp") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Timestamp") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s HeartbeatRecord) MarshalJSON() ([]byte, error) {
	type NoMethod HeartbeatRecord
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// IncludeReplicas: An `IncludeReplicas` contains a repeated set of
// `ReplicaSelection` which indicates the order in which replicas should be
// considered.
type IncludeReplicas struct {
	// AutoFailoverDisabled: If `true`, Spanner doesn't route requests to a replica
	// outside the <`include_replicas` list when all of the specified replicas are
	// unavailable or unhealthy. Default value is `false`.
	AutoFailoverDisabled bool `json:"autoFailoverDisabled,omitempty"`
	// ReplicaSelections: The directed read replica selector.
	ReplicaSelections []*ReplicaSelection `json:"replicaSelections,omitempty"`
	// ForceSendFields is a list of field names (e.g. "AutoFailoverDisabled") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AutoFailoverDisabled") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s IncludeReplicas) MarshalJSON() ([]byte, error) {
	type NoMethod IncludeReplicas
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// IncrementalBackupSpec: The specification for incremental backup chains. An
// incremental backup stores the delta of changes between a previous backup and
// the database contents at a given version time. An incremental backup chain
// consists of a full backup and zero or more successive incremental backups.
// The first backup created for an incremental backup chain is always a full
// backup.
type IncrementalBackupSpec struct {
}

// IndexAdvice: Recommendation to add new indexes to run queries more
// efficiently.
type IndexAdvice struct {
	// Ddl: Optional. DDL statements to add new indexes that will improve the
	// query.
	Ddl []string `json:"ddl,omitempty"`
	// ImprovementFactor: Optional. Estimated latency improvement factor. For
	// example if the query currently takes 500 ms to run and the estimated latency
	// with new indexes is 100 ms this field will be 5.
	ImprovementFactor float64 `json:"improvementFactor,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Ddl") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Ddl") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s IndexAdvice) MarshalJSON() ([]byte, error) {
	type NoMethod IndexAdvice
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *IndexAdvice) UnmarshalJSON(data []byte) error {
	type NoMethod IndexAdvice
	var s1 struct {
		ImprovementFactor gensupport.JSONFloat64 `json:"improvementFactor"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.ImprovementFactor = float64(s1.ImprovementFactor)
	return nil
}

// IndexedHotKey: A message representing a (sparse) collection of hot keys for
// specific key buckets.
type IndexedHotKey struct {
	// SparseHotKeys: A (sparse) mapping from key bucket index to the index of the
	// specific hot row key for that key bucket. The index of the hot row key can
	// be translated to the actual row key via the
	// ScanData.VisualizationData.indexed_keys repeated field.
	SparseHotKeys map[string]int64 `json:"sparseHotKeys,omitempty"`
	// ForceSendFields is a list of field names (e.g. "SparseHotKeys") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "SparseHotKeys") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s IndexedHotKey) MarshalJSON() ([]byte, error) {
	type NoMethod IndexedHotKey
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// IndexedKeyRangeInfos: A message representing a (sparse) collection of
// KeyRangeInfos for specific key buckets.
type IndexedKeyRangeInfos struct {
	// KeyRangeInfos: A (sparse) mapping from key bucket index to the KeyRangeInfos
	// for that key bucket.
	KeyRangeInfos map[string]KeyRangeInfos `json:"keyRangeInfos,omitempty"`
	// ForceSendFields is a list of field names (e.g. "KeyRangeInfos") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "KeyRangeInfos") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s IndexedKeyRangeInfos) MarshalJSON() ([]byte, error) {
	type NoMethod IndexedKeyRangeInfos
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Instance: An isolated set of Cloud Spanner resources on which databases can
// be hosted.
type Instance struct {
	// AutoscalingConfig: Optional. The autoscaling configuration. Autoscaling is
	// enabled if this field is set. When autoscaling is enabled, node_count and
	// processing_units are treated as OUTPUT_ONLY fields and reflect the current
	// compute capacity allocated to the instance.
	AutoscalingConfig *AutoscalingConfig `json:"autoscalingConfig,omitempty"`
	// Config: Required. The name of the instance's configuration. Values are of
	// the form `projects//instanceConfigs/`. See also InstanceConfig and
	// ListInstanceConfigs.
	Config string `json:"config,omitempty"`
	// CreateTime: Output only. The time at which the instance was created.
	CreateTime string `json:"createTime,omitempty"`
	// DefaultBackupScheduleType: Optional. Controls the default backup schedule
	// behavior for new databases within the instance. By default, a backup
	// schedule is created automatically when a new database is created in a new
	// instance. Note that the `AUTOMATIC` value isn't permitted for free
	// instances, as backups and backup schedules aren't supported for free
	// instances. In the `GetInstance` or `ListInstances` response, if the value of
	// `default_backup_schedule_type` isn't set, or set to `NONE`, Spanner doesn't
	// create a default backup schedule for new databases in the instance.
	//
	// Possible values:
	//   "DEFAULT_BACKUP_SCHEDULE_TYPE_UNSPECIFIED" - Not specified.
	//   "NONE" - A default backup schedule isn't created automatically when a new
	// database is created in the instance.
	//   "AUTOMATIC" - A default backup schedule is created automatically when a
	// new database is created in the instance. The default backup schedule creates
	// a full backup every 24 hours. These full backups are retained for 7 days.
	// You can edit or delete the default backup schedule once it's created.
	DefaultBackupScheduleType string `json:"defaultBackupScheduleType,omitempty"`
	// DisplayName: Required. The descriptive name for this instance as it appears
	// in UIs. Must be unique per project and between 4 and 30 characters in
	// length.
	DisplayName string `json:"displayName,omitempty"`
	// Edition: Optional. The `Edition` of the current instance.
	//
	// Possible values:
	//   "EDITION_UNSPECIFIED" - Edition not specified.
	//   "STANDARD" - Standard edition.
	//   "ENTERPRISE" - Enterprise edition.
	//   "ENTERPRISE_PLUS" - Enterprise Plus edition.
	Edition string `json:"edition,omitempty"`
	// EndpointUris: Deprecated. This field is not populated.
	EndpointUris []string `json:"endpointUris,omitempty"`
	// FreeInstanceMetadata: Free instance metadata. Only populated for free
	// instances.
	FreeInstanceMetadata *FreeInstanceMetadata `json:"freeInstanceMetadata,omitempty"`
	// InstanceType: The `InstanceType` of the current instance.
	//
	// Possible values:
	//   "INSTANCE_TYPE_UNSPECIFIED" - Not specified.
	//   "PROVISIONED" - Provisioned instances have dedicated resources, standard
	// usage limits and support.
	//   "FREE_INSTANCE" - Free instances provide no guarantee for dedicated
	// resources, [node_count, processing_units] should be 0. They come with
	// stricter usage limits and limited support.
	InstanceType string `json:"instanceType,omitempty"`
	// Labels: Cloud Labels are a flexible and lightweight mechanism for organizing
	// cloud resources into groups that reflect a customer's organizational needs
	// and deployment strategies. Cloud Labels can be used to filter collections of
	// resources. They can be used to control how resource metrics are aggregated.
	// And they can be used as arguments to policy management rules (e.g. route,
	// firewall, load balancing, etc.). * Label keys must be between 1 and 63
	// characters long and must conform to the following regular expression:
	// `a-z{0,62}`. * Label values must be between 0 and 63 characters long and
	// must conform to the regular expression `[a-z0-9_-]{0,63}`. * No more than 64
	// labels can be associated with a given resource. See https://goo.gl/xmQnxf
	// for more information on and examples of labels. If you plan to use labels in
	// your own code, please note that additional characters may be allowed in the
	// future. And so you are advised to use an internal label representation, such
	// as JSON, which doesn't rely upon specific characters being disallowed. For
	// example, representing labels as the string: name + "_" + value would prove
	// problematic if we were to allow "_" in a future release.
	Labels map[string]string `json:"labels,omitempty"`
	// Name: Required. A unique identifier for the instance, which cannot be
	// changed after the instance is created. Values are of the form
	// `projects//instances/a-z*[a-z0-9]`. The final segment of the name must be
	// between 2 and 64 characters in length.
	Name string `json:"name,omitempty"`
	// NodeCount: The number of nodes allocated to this instance. At most, one of
	// either `node_count` or `processing_units` should be present in the message.
	// Users can set the `node_count` field to specify the target number of nodes
	// allocated to the instance. If autoscaling is enabled, `node_count` is
	// treated as an `OUTPUT_ONLY` field and reflects the current number of nodes
	// allocated to the instance. This might be zero in API responses for instances
	// that are not yet in the `READY` state. If the instance has varying node
	// count across replicas (achieved by setting `asymmetric_autoscaling_options`
	// in the autoscaling configuration), the `node_count` set here is the maximum
	// node count across all replicas. For more information, see Compute capacity,
	// nodes, and processing units
	// (https://cloud.google.com/spanner/docs/compute-capacity).
	NodeCount int64 `json:"nodeCount,omitempty"`
	// ProcessingUnits: The number of processing units allocated to this instance.
	// At most, one of either `processing_units` or `node_count` should be present
	// in the message. Users can set the `processing_units` field to specify the
	// target number of processing units allocated to the instance. If autoscaling
	// is enabled, `processing_units` is treated as an `OUTPUT_ONLY` field and
	// reflects the current number of processing units allocated to the instance.
	// This might be zero in API responses for instances that are not yet in the
	// `READY` state. If the instance has varying processing units per replica
	// (achieved by setting `asymmetric_autoscaling_options` in the autoscaling
	// configuration), the `processing_units` set here is the maximum processing
	// units across all replicas. For more information, see Compute capacity, nodes
	// and processing units
	// (https://cloud.google.com/spanner/docs/compute-capacity).
	ProcessingUnits int64 `json:"processingUnits,omitempty"`
	// ReplicaComputeCapacity: Output only. Lists the compute capacity per
	// ReplicaSelection. A replica selection identifies a set of replicas with
	// common properties. Replicas identified by a ReplicaSelection are scaled with
	// the same compute capacity.
	ReplicaComputeCapacity []*ReplicaComputeCapacity `json:"replicaComputeCapacity,omitempty"`
	// State: Output only. The current instance state. For CreateInstance, the
	// state must be either omitted or set to `CREATING`. For UpdateInstance, the
	// state must be either omitted or set to `READY`.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Not specified.
	//   "CREATING" - The instance is still being created. Resources may not be
	// available yet, and operations such as database creation may not work.
	//   "READY" - The instance is fully created and ready to do work such as
	// creating databases.
	State string `json:"state,omitempty"`
	// UpdateTime: Output only. The time at which the instance was most recently
	// updated.
	UpdateTime string `json:"updateTime,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AutoscalingConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AutoscalingConfig") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Instance) MarshalJSON() ([]byte, error) {
	type NoMethod Instance
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InstanceConfig: A possible configuration for a Cloud Spanner instance.
// Configurations define the geographic placement of nodes and their
// replication.
type InstanceConfig struct {
	// BaseConfig: Base configuration name, e.g. projects//instanceConfigs/nam3,
	// based on which this configuration is created. Only set for user-managed
	// configurations. `base_config` must refer to a configuration of type
	// `GOOGLE_MANAGED` in the same project as this configuration.
	BaseConfig string `json:"baseConfig,omitempty"`
	// ConfigType: Output only. Whether this instance configuration is a
	// Google-managed or user-managed configuration.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Unspecified.
	//   "GOOGLE_MANAGED" - Google-managed configuration.
	//   "USER_MANAGED" - User-managed configuration.
	ConfigType string `json:"configType,omitempty"`
	// DisplayName: The name of this instance configuration as it appears in UIs.
	DisplayName string `json:"displayName,omitempty"`
	// Etag: etag is used for optimistic concurrency control as a way to help
	// prevent simultaneous updates of a instance configuration from overwriting
	// each other. It is strongly suggested that systems make use of the etag in
	// the read-modify-write cycle to perform instance configuration updates in
	// order to avoid race conditions: An etag is returned in the response which
	// contains instance configurations, and systems are expected to put that etag
	// in the request to update instance configuration to ensure that their change
	// is applied to the same version of the instance configuration. If no etag is
	// provided in the call to update the instance configuration, then the existing
	// instance configuration is overwritten blindly.
	Etag string `json:"etag,omitempty"`
	// FreeInstanceAvailability: Output only. Describes whether free instances are
	// available to be created in this instance configuration.
	//
	// Possible values:
	//   "FREE_INSTANCE_AVAILABILITY_UNSPECIFIED" - Not specified.
	//   "AVAILABLE" - Indicates that free instances are available to be created in
	// this instance configuration.
	//   "UNSUPPORTED" - Indicates that free instances are not supported in this
	// instance configuration.
	//   "DISABLED" - Indicates that free instances are currently not available to
	// be created in this instance configuration.
	//   "QUOTA_EXCEEDED" - Indicates that additional free instances cannot be
	// created in this instance configuration because the project has reached its
	// limit of free instances.
	FreeInstanceAvailability string `json:"freeInstanceAvailability,omitempty"`
	// Labels: Cloud Labels are a flexible and lightweight mechanism for organizing
	// cloud resources into groups that reflect a customer's organizational needs
	// and deployment strategies. Cloud Labels can be used to filter collections of
	// resources. They can be used to control how resource metrics are aggregated.
	// And they can be used as arguments to policy management rules (e.g. route,
	// firewall, load balancing, etc.). * Label keys must be between 1 and 63
	// characters long and must conform to the following regular expression:
	// `a-z{0,62}`. * Label values must be between 0 and 63 characters long and
	// must conform to the regular expression `[a-z0-9_-]{0,63}`. * No more than 64
	// labels can be associated with a given resource. See https://goo.gl/xmQnxf
	// for more information on and examples of labels. If you plan to use labels in
	// your own code, please note that additional characters may be allowed in the
	// future. Therefore, you are advised to use an internal label representation,
	// such as JSON, which doesn't rely upon specific characters being disallowed.
	// For example, representing labels as the string: name + "_" + value would
	// prove problematic if we were to allow "_" in a future release.
	Labels map[string]string `json:"labels,omitempty"`
	// LeaderOptions: Allowed values of the "default_leader" schema option for
	// databases in instances that use this instance configuration.
	LeaderOptions []string `json:"leaderOptions,omitempty"`
	// Name: A unique identifier for the instance configuration. Values are of the
	// form `projects//instanceConfigs/a-z*`. User instance configuration must
	// start with `custom-`.
	Name string `json:"name,omitempty"`
	// OptionalReplicas: Output only. The available optional replicas to choose
	// from for user-managed configurations. Populated for Google-managed
	// configurations.
	OptionalReplicas []*ReplicaInfo `json:"optionalReplicas,omitempty"`
	// QuorumType: Output only. The `QuorumType` of the instance configuration.
	//
	// Possible values:
	//   "QUORUM_TYPE_UNSPECIFIED" - Quorum type not specified.
	//   "REGION" - An instance configuration tagged with `REGION` quorum type
	// forms a write quorum in a single region.
	//   "DUAL_REGION" - An instance configuration tagged with the `DUAL_REGION`
	// quorum type forms a write quorum with exactly two read-write regions in a
	// multi-region configuration. This instance configuration requires failover in
	// the event of regional failures.
	//   "MULTI_REGION" - An instance configuration tagged with the `MULTI_REGION`
	// quorum type forms a write quorum from replicas that are spread across more
	// than one region in a multi-region configuration.
	QuorumType string `json:"quorumType,omitempty"`
	// Reconciling: Output only. If true, the instance configuration is being
	// created or updated. If false, there are no ongoing operations for the
	// instance configuration.
	Reconciling bool `json:"reconciling,omitempty"`
	// Replicas: The geographic placement of nodes in this instance configuration
	// and their replication properties. To create user-managed configurations,
	// input `replicas` must include all replicas in `replicas` of the
	// `base_config` and include one or more replicas in the `optional_replicas` of
	// the `base_config`.
	Replicas []*ReplicaInfo `json:"replicas,omitempty"`
	// State: Output only. The current instance configuration state. Applicable
	// only for `USER_MANAGED` configurations.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Not specified.
	//   "CREATING" - The instance configuration is still being created.
	//   "READY" - The instance configuration is fully created and ready to be used
	// to create instances.
	State string `json:"state,omitempty"`
	// StorageLimitPerProcessingUnit: Output only. The storage limit in bytes per
	// processing unit.
	StorageLimitPerProcessingUnit int64 `json:"storageLimitPerProcessingUnit,omitempty,string"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "BaseConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BaseConfig") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s InstanceConfig) MarshalJSON() ([]byte, error) {
	type NoMethod InstanceConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InstanceEncryptionConfig: Encryption configuration for a Cloud Spanner
// database.
type InstanceEncryptionConfig struct {
	// KmsKeyName: Optional. This field is maintained for backwards compatibility.
	// For new callers, we recommend using `kms_key_names` to specify the KMS key.
	// Only use `kms_key_name` if the location of the KMS key matches the database
	// instance's configuration (location) exactly. For example, if the KMS
	// location is in `us-central1` or `nam3`, then the database instance must also
	// be in `us-central1` or `nam3`. The Cloud KMS key that is used to encrypt and
	// decrypt the restored database. Values are of the form
	// `projects//locations//keyRings//cryptoKeys/`.
	KmsKeyName string `json:"kmsKeyName,omitempty"`
	// KmsKeyNames: Optional. Specifies the KMS configuration for one or more keys
	// used to encrypt the database. Values are of the form
	// `projects//locations//keyRings//cryptoKeys/`. The keys referenced by
	// `kms_key_names` must fully cover all regions of the database's instance
	// configuration. Some examples: * For regional (single-region) instance
	// configurations, specify a regional location KMS key. * For multi-region
	// instance configurations of type `GOOGLE_MANAGED`, either specify a
	// multi-region location KMS key or multiple regional location KMS keys that
	// cover all regions in the instance configuration. * For an instance
	// configuration of type `USER_MANAGED`, specify only regional location KMS
	// keys to cover each region in the instance configuration. Multi-region
	// location KMS keys aren't supported for `USER_MANAGED` type instance
	// configurations.
	KmsKeyNames []string `json:"kmsKeyNames,omitempty"`
	// ForceSendFields is a list of field names (e.g. "KmsKeyName") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "KmsKeyName") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s InstanceEncryptionConfig) MarshalJSON() ([]byte, error) {
	type NoMethod InstanceEncryptionConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InstanceOperationProgress: Encapsulates progress related information for a
// Cloud Spanner long running instance operations.
type InstanceOperationProgress struct {
	// EndTime: If set, the time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// ProgressPercent: Percent completion of the operation. Values are between 0
	// and 100 inclusive.
	ProgressPercent int64 `json:"progressPercent,omitempty"`
	// StartTime: Time the request was received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EndTime") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EndTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s InstanceOperationProgress) MarshalJSON() ([]byte, error) {
	type NoMethod InstanceOperationProgress
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InstancePartition: An isolated set of Cloud Spanner resources that databases
// can define placements on.
type InstancePartition struct {
	// AutoscalingConfig: Optional. The autoscaling configuration. Autoscaling is
	// enabled if this field is set. When autoscaling is enabled, fields in
	// compute_capacity are treated as OUTPUT_ONLY fields and reflect the current
	// compute capacity allocated to the instance partition.
	AutoscalingConfig *AutoscalingConfig `json:"autoscalingConfig,omitempty"`
	// Config: Required. The name of the instance partition's configuration. Values
	// are of the form `projects//instanceConfigs/`. See also InstanceConfig and
	// ListInstanceConfigs.
	Config string `json:"config,omitempty"`
	// CreateTime: Output only. The time at which the instance partition was
	// created.
	CreateTime string `json:"createTime,omitempty"`
	// DisplayName: Required. The descriptive name for this instance partition as
	// it appears in UIs. Must be unique per project and between 4 and 30
	// characters in length.
	DisplayName string `json:"displayName,omitempty"`
	// Etag: Used for optimistic concurrency control as a way to help prevent
	// simultaneous updates of a instance partition from overwriting each other. It
	// is strongly suggested that systems make use of the etag in the
	// read-modify-write cycle to perform instance partition updates in order to
	// avoid race conditions: An etag is returned in the response which contains
	// instance partitions, and systems are expected to put that etag in the
	// request to update instance partitions to ensure that their change will be
	// applied to the same version of the instance partition. If no etag is
	// provided in the call to update instance partition, then the existing
	// instance partition is overwritten blindly.
	Etag string `json:"etag,omitempty"`
	// Name: Required. A unique identifier for the instance partition. Values are
	// of the form `projects//instances//instancePartitions/a-z*[a-z0-9]`. The
	// final segment of the name must be between 2 and 64 characters in length. An
	// instance partition's name cannot be changed after the instance partition is
	// created.
	Name string `json:"name,omitempty"`
	// NodeCount: The number of nodes allocated to this instance partition. Users
	// can set the `node_count` field to specify the target number of nodes
	// allocated to the instance partition. If autoscaling is enabled, node_count
	// is treated as an OUTPUT_ONLY field and reflects the current number of nodes
	// allocated to the instance partition. This may be zero in API responses for
	// instance partitions that are not yet in state `READY`.
	NodeCount int64 `json:"nodeCount,omitempty"`
	// ProcessingUnits: The number of processing units allocated to this instance
	// partition. Users can set the `processing_units` field to specify the target
	// number of processing units allocated to the instance partition. If
	// autoscaling is enabled, processing_units is treated as an OUTPUT_ONLY field
	// and reflects the current number of processing units allocated to the
	// instance partition. This might be zero in API responses for instance
	// partitions that are not yet in the `READY` state.
	ProcessingUnits int64 `json:"processingUnits,omitempty"`
	// ReferencingBackups: Output only. Deprecated: This field is not populated.
	// Output only. The names of the backups that reference this instance
	// partition. Referencing backups should share the parent instance. The
	// existence of any referencing backup prevents the instance partition from
	// being deleted.
	ReferencingBackups []string `json:"referencingBackups,omitempty"`
	// ReferencingDatabases: Output only. The names of the databases that reference
	// this instance partition. Referencing databases should share the parent
	// instance. The existence of any referencing database prevents the instance
	// partition from being deleted.
	ReferencingDatabases []string `json:"referencingDatabases,omitempty"`
	// State: Output only. The current instance partition state.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - Not specified.
	//   "CREATING" - The instance partition is still being created. Resources may
	// not be available yet, and operations such as creating placements using this
	// instance partition may not work.
	//   "READY" - The instance partition is fully created and ready to do work
	// such as creating placements and using in databases.
	State string `json:"state,omitempty"`
	// UpdateTime: Output only. The time at which the instance partition was most
	// recently updated.
	UpdateTime string `json:"updateTime,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "AutoscalingConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "AutoscalingConfig") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s InstancePartition) MarshalJSON() ([]byte, error) {
	type NoMethod InstancePartition
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// InstanceReplicaSelection: ReplicaSelection identifies replicas with common
// properties.
type InstanceReplicaSelection struct {
	// Location: Required. Name of the location of the replicas (for example,
	// "us-central1").
	Location string `json:"location,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Location") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Location") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s InstanceReplicaSelection) MarshalJSON() ([]byte, error) {
	type NoMethod InstanceReplicaSelection
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Key: A split key.
type Key struct {
	// KeyParts: Required. The column values making up the split key.
	KeyParts []interface{} `json:"keyParts,omitempty"`
	// ForceSendFields is a list of field names (e.g. "KeyParts") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "KeyParts") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Key) MarshalJSON() ([]byte, error) {
	type NoMethod Key
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// KeyRange: KeyRange represents a range of rows in a table or index. A range
// has a start key and an end key. These keys can be open or closed, indicating
// if the range includes rows with that key. Keys are represented by lists,
// where the ith value in the list corresponds to the ith component of the
// table or index primary key. Individual values are encoded as described here.
// For example, consider the following table definition: CREATE TABLE
// UserEvents ( UserName STRING(MAX), EventDate STRING(10) ) PRIMARY
// KEY(UserName, EventDate); The following keys name rows in this table: "Bob",
// "2014-09-23" Since the `UserEvents` table's `PRIMARY KEY` clause names two
// columns, each `UserEvents` key has two elements; the first is the
// `UserName`, and the second is the `EventDate`. Key ranges with multiple
// components are interpreted lexicographically by component using the table or
// index key's declared sort order. For example, the following range returns
// all events for user "Bob" that occurred in the year 2015: "start_closed":
// ["Bob", "2015-01-01"] "end_closed": ["Bob", "2015-12-31"] Start and end keys
// can omit trailing key components. This affects the inclusion and exclusion
// of rows that exactly match the provided key components: if the key is
// closed, then rows that exactly match the provided components are included;
// if the key is open, then rows that exactly match are not included. For
// example, the following range includes all events for "Bob" that occurred
// during and after the year 2000: "start_closed": ["Bob", "2000-01-01"]
// "end_closed": ["Bob"] The next example retrieves all events for "Bob":
// "start_closed": ["Bob"] "end_closed": ["Bob"] To retrieve events before the
// year 2000: "start_closed": ["Bob"] "end_open": ["Bob", "2000-01-01"] The
// following range includes all rows in the table: "start_closed": []
// "end_closed": [] This range returns all users whose `UserName` begins with
// any character from A to C: "start_closed": ["A"] "end_open": ["D"] This
// range returns all users whose `UserName` begins with B: "start_closed":
// ["B"] "end_open": ["C"] Key ranges honor column sort order. For example,
// suppose a table is defined as follows: CREATE TABLE DescendingSortedTable {
// Key INT64, ... ) PRIMARY KEY(Key DESC); The following range retrieves all
// rows with key values between 1 and 100 inclusive: "start_closed": ["100"]
// "end_closed": ["1"] Note that 100 is passed as the start, and 1 is passed as
// the end, because `Key` is a descending column in the schema.
type KeyRange struct {
	// EndClosed: If the end is closed, then the range includes all rows whose
	// first `len(end_closed)` key columns exactly match `end_closed`.
	EndClosed []interface{} `json:"endClosed,omitempty"`
	// EndOpen: If the end is open, then the range excludes rows whose first
	// `len(end_open)` key columns exactly match `end_open`.
	EndOpen []interface{} `json:"endOpen,omitempty"`
	// StartClosed: If the start is closed, then the range includes all rows whose
	// first `len(start_closed)` key columns exactly match `start_closed`.
	StartClosed []interface{} `json:"startClosed,omitempty"`
	// StartOpen: If the start is open, then the range excludes rows whose first
	// `len(start_open)` key columns exactly match `start_open`.
	StartOpen []interface{} `json:"startOpen,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EndClosed") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EndClosed") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s KeyRange) MarshalJSON() ([]byte, error) {
	type NoMethod KeyRange
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// KeyRangeInfo: A message representing information for a key range (possibly
// one key).
type KeyRangeInfo struct {
	// ContextValues: The list of context values for this key range.
	ContextValues []*ContextValue `json:"contextValues,omitempty"`
	// EndKeyIndex: The index of the end key in indexed_keys.
	EndKeyIndex int64 `json:"endKeyIndex,omitempty"`
	// Info: Information about this key range, for all metrics.
	Info *LocalizedString `json:"info,omitempty"`
	// KeysCount: The number of keys this range covers.
	KeysCount int64 `json:"keysCount,omitempty,string"`
	// Metric: The name of the metric. e.g. "latency".
	Metric *LocalizedString `json:"metric,omitempty"`
	// StartKeyIndex: The index of the start key in indexed_keys.
	StartKeyIndex int64 `json:"startKeyIndex,omitempty"`
	// TimeOffset: The time offset. This is the time since the start of the time
	// interval.
	TimeOffset string `json:"timeOffset,omitempty"`
	// Unit: The unit of the metric. This is an unstructured field and will be
	// mapped as is to the user.
	Unit *LocalizedString `json:"unit,omitempty"`
	// Value: The value of the metric.
	Value float64 `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ContextValues") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ContextValues") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s KeyRangeInfo) MarshalJSON() ([]byte, error) {
	type NoMethod KeyRangeInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *KeyRangeInfo) UnmarshalJSON(data []byte) error {
	type NoMethod KeyRangeInfo
	var s1 struct {
		Value gensupport.JSONFloat64 `json:"value"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Value = float64(s1.Value)
	return nil
}

// KeyRangeInfos: A message representing a list of specific information for
// multiple key ranges.
type KeyRangeInfos struct {
	// Infos: The list individual KeyRangeInfos.
	Infos []*KeyRangeInfo `json:"infos,omitempty"`
	// TotalSize: The total size of the list of all KeyRangeInfos. This may be
	// larger than the number of repeated messages above. If that is the case, this
	// number may be used to determine how many are not being shown.
	TotalSize int64 `json:"totalSize,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Infos") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Infos") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s KeyRangeInfos) MarshalJSON() ([]byte, error) {
	type NoMethod KeyRangeInfos
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// KeySet: `KeySet` defines a collection of Cloud Spanner keys and/or key
// ranges. All the keys are expected to be in the same table or index. The keys
// need not be sorted in any particular way. If the same key is specified
// multiple times in the set (for example if two ranges, two keys, or a key and
// a range overlap), Cloud Spanner behaves as if the key were only specified
// once.
type KeySet struct {
	// All: For convenience `all` can be set to `true` to indicate that this
	// `KeySet` matches all keys in the table or index. Note that any keys
	// specified in `keys` or `ranges` are only yielded once.
	All bool `json:"all,omitempty"`
	// Keys: A list of specific keys. Entries in `keys` should have exactly as many
	// elements as there are columns in the primary or index key with which this
	// `KeySet` is used. Individual key values are encoded as described here.
	Keys [][]interface{} `json:"keys,omitempty"`
	// Ranges: A list of key ranges. See KeyRange for more information about key
	// range specifications.
	Ranges []*KeyRange `json:"ranges,omitempty"`
	// ForceSendFields is a list of field names (e.g. "All") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "All") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s KeySet) MarshalJSON() ([]byte, error) {
	type NoMethod KeySet
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListBackupOperationsResponse: The response for ListBackupOperations.
type ListBackupOperationsResponse struct {
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListBackupOperations call to fetch more of the matching metadata.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Operations: The list of matching backup long-running operations. Each
	// operation's name will be prefixed by the backup's name. The operation's
	// metadata field type `metadata.type_url` describes the type of the metadata.
	// Operations returned include those that are pending or have
	// completed/failed/canceled within the last 7 days. Operations returned are
	// ordered by `operation.metadata.value.progress.start_time` in descending
	// order starting from the most recently started operation.
	Operations []*Operation `json:"operations,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListBackupOperationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListBackupOperationsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListBackupSchedulesResponse: The response for ListBackupSchedules.
type ListBackupSchedulesResponse struct {
	// BackupSchedules: The list of backup schedules for a database.
	BackupSchedules []*BackupSchedule `json:"backupSchedules,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListBackupSchedules call to fetch more of the schedules.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "BackupSchedules") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BackupSchedules") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListBackupSchedulesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListBackupSchedulesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListBackupsResponse: The response for ListBackups.
type ListBackupsResponse struct {
	// Backups: The list of matching backups. Backups returned are ordered by
	// `create_time` in descending order, starting from the most recent
	// `create_time`.
	Backups []*Backup `json:"backups,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent ListBackups
	// call to fetch more of the matching backups.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Backups") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Backups") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListBackupsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListBackupsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListDatabaseOperationsResponse: The response for ListDatabaseOperations.
type ListDatabaseOperationsResponse struct {
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListDatabaseOperations call to fetch more of the matching metadata.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Operations: The list of matching database long-running operations. Each
	// operation's name will be prefixed by the database's name. The operation's
	// metadata field type `metadata.type_url` describes the type of the metadata.
	Operations []*Operation `json:"operations,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListDatabaseOperationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListDatabaseOperationsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListDatabaseRolesResponse: The response for ListDatabaseRoles.
type ListDatabaseRolesResponse struct {
	// DatabaseRoles: Database roles that matched the request.
	DatabaseRoles []*DatabaseRole `json:"databaseRoles,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListDatabaseRoles call to fetch more of the matching roles.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "DatabaseRoles") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DatabaseRoles") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListDatabaseRolesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListDatabaseRolesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListDatabasesResponse: The response for ListDatabases.
type ListDatabasesResponse struct {
	// Databases: Databases that matched the request.
	Databases []*Database `json:"databases,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent ListDatabases
	// call to fetch more of the matching databases.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Databases") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Databases") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListDatabasesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListDatabasesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListInstanceConfigOperationsResponse: The response for
// ListInstanceConfigOperations.
type ListInstanceConfigOperationsResponse struct {
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListInstanceConfigOperations call to fetch more of the matching metadata.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Operations: The list of matching instance configuration long-running
	// operations. Each operation's name will be prefixed by the name of the
	// instance configuration. The operation's metadata field type
	// `metadata.type_url` describes the type of the metadata.
	Operations []*Operation `json:"operations,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListInstanceConfigOperationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListInstanceConfigOperationsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListInstanceConfigsResponse: The response for ListInstanceConfigs.
type ListInstanceConfigsResponse struct {
	// InstanceConfigs: The list of requested instance configurations.
	InstanceConfigs []*InstanceConfig `json:"instanceConfigs,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListInstanceConfigs call to fetch more of the matching instance
	// configurations.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "InstanceConfigs") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "InstanceConfigs") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListInstanceConfigsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListInstanceConfigsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListInstancePartitionOperationsResponse: The response for
// ListInstancePartitionOperations.
type ListInstancePartitionOperationsResponse struct {
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListInstancePartitionOperations call to fetch more of the matching metadata.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Operations: The list of matching instance partition long-running operations.
	// Each operation's name will be prefixed by the instance partition's name. The
	// operation's metadata field type `metadata.type_url` describes the type of
	// the metadata.
	Operations []*Operation `json:"operations,omitempty"`
	// UnreachableInstancePartitions: The list of unreachable instance partitions.
	// It includes the names of instance partitions whose operation metadata could
	// not be retrieved within instance_partition_deadline.
	UnreachableInstancePartitions []string `json:"unreachableInstancePartitions,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListInstancePartitionOperationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListInstancePartitionOperationsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListInstancePartitionsResponse: The response for ListInstancePartitions.
type ListInstancePartitionsResponse struct {
	// InstancePartitions: The list of requested instancePartitions.
	InstancePartitions []*InstancePartition `json:"instancePartitions,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent
	// ListInstancePartitions call to fetch more of the matching instance
	// partitions.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Unreachable: The list of unreachable instances or instance partitions. It
	// includes the names of instances or instance partitions whose metadata could
	// not be retrieved within instance_partition_deadline.
	Unreachable []string `json:"unreachable,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "InstancePartitions") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "InstancePartitions") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListInstancePartitionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListInstancePartitionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListInstancesResponse: The response for ListInstances.
type ListInstancesResponse struct {
	// Instances: The list of requested instances.
	Instances []*Instance `json:"instances,omitempty"`
	// NextPageToken: `next_page_token` can be sent in a subsequent ListInstances
	// call to fetch more of the matching instances.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Unreachable: The list of unreachable instances. It includes the names of
	// instances whose metadata could not be retrieved within instance_deadline.
	Unreachable []string `json:"unreachable,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Instances") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Instances") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListInstancesResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListInstancesResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListOperationsResponse: The response message for Operations.ListOperations.
type ListOperationsResponse struct {
	// NextPageToken: The standard List next-page token.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Operations: A list of operations that matches the specified filter in the
	// request.
	Operations []*Operation `json:"operations,omitempty"`
	// Unreachable: Unordered list. Unreachable resources. Populated when the
	// request sets `ListOperationsRequest.return_partial_success` and reads across
	// collections. For example, when attempting to list all resources across all
	// supported locations.
	Unreachable []string `json:"unreachable,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListOperationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListOperationsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListScansResponse: Response method from the ListScans method.
type ListScansResponse struct {
	// NextPageToken: Token to retrieve the next page of results, or empty if there
	// are no more results in the list.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Scans: Available scans based on the list query parameters.
	Scans []*Scan `json:"scans,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListScansResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListScansResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ListSessionsResponse: The response for ListSessions.
type ListSessionsResponse struct {
	// NextPageToken: `next_page_token` can be sent in a subsequent ListSessions
	// call to fetch more of the matching sessions.
	NextPageToken string `json:"nextPageToken,omitempty"`
	// Sessions: The list of requested sessions.
	Sessions []*Session `json:"sessions,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NextPageToken") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ListSessionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod ListSessionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// LocalizedString: A message representing a user-facing string whose value may
// need to be translated before being displayed.
type LocalizedString struct {
	// Args: A map of arguments used when creating the localized message. Keys
	// represent parameter names which may be used by the localized version when
	// substituting dynamic values.
	Args map[string]string `json:"args,omitempty"`
	// Message: The canonical English version of this message. If no token is
	// provided or the front-end has no message associated with the token, this
	// text will be displayed as-is.
	Message string `json:"message,omitempty"`
	// Token: The token identifying the message, e.g. 'METRIC_READ_CPU'. This
	// should be unique within the service.
	Token string `json:"token,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Args") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Args") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s LocalizedString) MarshalJSON() ([]byte, error) {
	type NoMethod LocalizedString
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Metric: A message representing the actual monitoring data, values for each
// key bucket over time, of a metric.
type Metric struct {
	// Aggregation: The aggregation function used to aggregate each key bucket
	//
	// Possible values:
	//   "AGGREGATION_UNSPECIFIED" - Required default value.
	//   "MAX" - Use the maximum of all values.
	//   "SUM" - Use the sum of all values.
	Aggregation string `json:"aggregation,omitempty"`
	// Category: The category of the metric, e.g. "Activity", "Alerts", "Reads",
	// etc.
	Category *LocalizedString `json:"category,omitempty"`
	// Derived: The references to numerator and denominator metrics for a derived
	// metric.
	Derived *DerivedMetric `json:"derived,omitempty"`
	// DisplayLabel: The displayed label of the metric.
	DisplayLabel *LocalizedString `json:"displayLabel,omitempty"`
	// HasNonzeroData: Whether the metric has any non-zero data.
	HasNonzeroData bool `json:"hasNonzeroData,omitempty"`
	// HotValue: The value that is considered hot for the metric. On a per metric
	// basis hotness signals high utilization and something that might potentially
	// be a cause for concern by the end user. hot_value is used to calibrate and
	// scale visual color scales.
	HotValue float64 `json:"hotValue,omitempty"`
	// IndexedHotKeys: The (sparse) mapping from time index to an IndexedHotKey
	// message, representing those time intervals for which there are hot keys.
	IndexedHotKeys map[string]IndexedHotKey `json:"indexedHotKeys,omitempty"`
	// IndexedKeyRangeInfos: The (sparse) mapping from time interval index to an
	// IndexedKeyRangeInfos message, representing those time intervals for which
	// there are informational messages concerning key ranges.
	IndexedKeyRangeInfos map[string]IndexedKeyRangeInfos `json:"indexedKeyRangeInfos,omitempty"`
	// Info: Information about the metric.
	Info *LocalizedString `json:"info,omitempty"`
	// Matrix: The data for the metric as a matrix.
	Matrix *MetricMatrix `json:"matrix,omitempty"`
	// Unit: The unit of the metric.
	Unit *LocalizedString `json:"unit,omitempty"`
	// Visible: Whether the metric is visible to the end user.
	Visible bool `json:"visible,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Aggregation") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Aggregation") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Metric) MarshalJSON() ([]byte, error) {
	type NoMethod Metric
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *Metric) UnmarshalJSON(data []byte) error {
	type NoMethod Metric
	var s1 struct {
		HotValue gensupport.JSONFloat64 `json:"hotValue"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.HotValue = float64(s1.HotValue)
	return nil
}

// MetricMatrix: A message representing a matrix of floats.
type MetricMatrix struct {
	// Rows: The rows of the matrix.
	Rows []*MetricMatrixRow `json:"rows,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Rows") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Rows") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MetricMatrix) MarshalJSON() ([]byte, error) {
	type NoMethod MetricMatrix
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MetricMatrixRow: A message representing a row of a matrix of floats.
type MetricMatrixRow struct {
	// Cols: The columns of the row.
	Cols []float64 `json:"cols,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Cols") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Cols") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MetricMatrixRow) MarshalJSON() ([]byte, error) {
	type NoMethod MetricMatrixRow
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

func (s *MetricMatrixRow) UnmarshalJSON(data []byte) error {
	type NoMethod MetricMatrixRow
	var s1 struct {
		Cols []gensupport.JSONFloat64 `json:"cols"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Cols = make([]float64, len(s1.Cols))
	for i := range s1.Cols {
		s.Cols[i] = float64(s1.Cols[i])
	}
	return nil
}

// Mod: A mod describes all data changes in a watched table row.
type Mod struct {
	// Keys: Returns the value of the primary key of the modified row.
	Keys []*ModValue `json:"keys,omitempty"`
	// NewValues: Returns the new values after the change for the modified columns.
	// Always empty for DELETE.
	NewValues []*ModValue `json:"newValues,omitempty"`
	// OldValues: Returns the old values before the change for the modified
	// columns. Always empty for INSERT, or if old values are not being captured
	// specified by value_capture_type.
	OldValues []*ModValue `json:"oldValues,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Keys") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Keys") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Mod) MarshalJSON() ([]byte, error) {
	type NoMethod Mod
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ModValue: Returns the value and associated metadata for a particular field
// of the Mod.
type ModValue struct {
	// ColumnMetadataIndex: Index within the repeated column_metadata field, to
	// obtain the column metadata for the column that was modified.
	ColumnMetadataIndex int64 `json:"columnMetadataIndex,omitempty"`
	// Value: The value of the column.
	Value interface{} `json:"value,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ColumnMetadataIndex") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ColumnMetadataIndex") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ModValue) MarshalJSON() ([]byte, error) {
	type NoMethod ModValue
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MoveInEvent: Describes move-in of the key ranges into the change stream
// partition identified by partition_token. To maintain processing the changes
// for a particular key in timestamp order, the query processing the change
// stream partition identified by partition_token should not advance beyond the
// partition event record commit timestamp until the queries processing the
// source change stream partitions have processed all change stream records
// with timestamps <= the partition event record commit timestamp.
type MoveInEvent struct {
	// SourcePartitionToken: An unique partition identifier describing the source
	// change stream partition that recorded changes for the key range that is
	// moving into this partition.
	SourcePartitionToken string `json:"sourcePartitionToken,omitempty"`
	// ForceSendFields is a list of field names (e.g. "SourcePartitionToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "SourcePartitionToken") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MoveInEvent) MarshalJSON() ([]byte, error) {
	type NoMethod MoveInEvent
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MoveInstanceRequest: The request for MoveInstance.
type MoveInstanceRequest struct {
	// TargetConfig: Required. The target instance configuration where to move the
	// instance. Values are of the form `projects//instanceConfigs/`.
	TargetConfig string `json:"targetConfig,omitempty"`
	// TargetDatabaseMoveConfigs: Optional. The configuration for each database in
	// the target instance configuration.
	TargetDatabaseMoveConfigs []*DatabaseMoveConfig `json:"targetDatabaseMoveConfigs,omitempty"`
	// ForceSendFields is a list of field names (e.g. "TargetConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "TargetConfig") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MoveInstanceRequest) MarshalJSON() ([]byte, error) {
	type NoMethod MoveInstanceRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MoveOutEvent: Describes move-out of the key ranges out of the change stream
// partition identified by partition_token. To maintain processing the changes
// for a particular key in timestamp order, the query processing the
// MoveOutEvent in the partition identified by partition_token should inform
// the queries processing the destination partitions that they can unblock and
// proceed processing records past the commit_timestamp.
type MoveOutEvent struct {
	// DestinationPartitionToken: An unique partition identifier describing the
	// destination change stream partition that will record changes for the key
	// range that is moving out of this partition.
	DestinationPartitionToken string `json:"destinationPartitionToken,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DestinationPartitionToken")
	// to unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DestinationPartitionToken") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MoveOutEvent) MarshalJSON() ([]byte, error) {
	type NoMethod MoveOutEvent
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MultiplexedSessionPrecommitToken: When a read-write transaction is executed
// on a multiplexed session, this precommit token is sent back to the client as
// a part of the Transaction message in the BeginTransaction response and also
// as a part of the ResultSet and PartialResultSet responses.
type MultiplexedSessionPrecommitToken struct {
	// PrecommitToken: Opaque precommit token.
	PrecommitToken string `json:"precommitToken,omitempty"`
	// SeqNum: An incrementing seq number is generated on every precommit token
	// that is returned. Clients should remember the precommit token with the
	// highest sequence number from the current transaction attempt.
	SeqNum int64 `json:"seqNum,omitempty"`
	// ForceSendFields is a list of field names (e.g. "PrecommitToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "PrecommitToken") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MultiplexedSessionPrecommitToken) MarshalJSON() ([]byte, error) {
	type NoMethod MultiplexedSessionPrecommitToken
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Mutation: A modification to one or more Cloud Spanner rows. Mutations can be
// applied to a Cloud Spanner database by sending them in a Commit call.
type Mutation struct {
	// Ack: Ack a message from a queue.
	Ack *Ack `json:"ack,omitempty"`
	// Delete: Delete rows from a table. Succeeds whether or not the named rows
	// were present.
	Delete *Delete `json:"delete,omitempty"`
	// Insert: Insert new rows in a table. If any of the rows already exist, the
	// write or transaction fails with error `ALREADY_EXISTS`.
	Insert *Write `json:"insert,omitempty"`
	// InsertOrUpdate: Like insert, except that if the row already exists, then its
	// column values are overwritten with the ones provided. Any column values not
	// explicitly written are preserved. When using insert_or_update, just as when
	// using insert, all `NOT NULL` columns in the table must be given a value.
	// This holds true even when the row already exists and will therefore actually
	// be updated.
	InsertOrUpdate *Write `json:"insertOrUpdate,omitempty"`
	// Replace: Like insert, except that if the row already exists, it is deleted,
	// and the column values provided are inserted instead. Unlike
	// insert_or_update, this means any values not explicitly written become
	// `NULL`. In an interleaved table, if you create the child table with the `ON
	// DELETE CASCADE` annotation, then replacing a parent row also deletes the
	// child rows. Otherwise, you must delete the child rows before you replace the
	// parent row.
	Replace *Write `json:"replace,omitempty"`
	// Send: Send a message to a queue.
	Send *Send `json:"send,omitempty"`
	// Update: Update existing rows in a table. If any of the rows does not already
	// exist, the transaction fails with error `NOT_FOUND`.
	Update *Write `json:"update,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Ack") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Ack") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Mutation) MarshalJSON() ([]byte, error) {
	type NoMethod Mutation
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// MutationGroup: A group of mutations to be committed together. Related
// mutations should be placed in a group. For example, two mutations inserting
// rows with the same primary key prefix in both parent and child tables are
// related.
type MutationGroup struct {
	// Mutations: Required. The mutations in this group.
	Mutations []*Mutation `json:"mutations,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Mutations") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Mutations") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s MutationGroup) MarshalJSON() ([]byte, error) {
	type NoMethod MutationGroup
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Operation: This resource represents a long-running operation that is the
// result of a network API call.
type Operation struct {
	// Done: If the value is `false`, it means the operation is still in progress.
	// If `true`, the operation is completed, and either `error` or `response` is
	// available.
	Done bool `json:"done,omitempty"`
	// Error: The error result of the operation in case of failure or cancellation.
	Error *Status `json:"error,omitempty"`
	// Metadata: Service-specific metadata associated with the operation. It
	// typically contains progress information and common metadata such as create
	// time. Some services might not provide such metadata. Any method that returns
	// a long-running operation should document the metadata type, if any.
	Metadata googleapi.RawMessage `json:"metadata,omitempty"`
	// Name: The server-assigned name, which is only unique within the same service
	// that originally returns it. If you use the default HTTP mapping, the `name`
	// should be a resource name ending with `operations/{unique_id}`.
	Name string `json:"name,omitempty"`
	// Response: The normal, successful response of the operation. If the original
	// method returns no data on success, such as `Delete`, the response is
	// `google.protobuf.Empty`. If the original method is standard
	// `Get`/`Create`/`Update`, the response should be the resource. For other
	// methods, the response should have the type `XxxResponse`, where `Xxx` is the
	// original method name. For example, if the original method name is
	// `TakeSnapshot()`, the inferred response type is `TakeSnapshotResponse`.
	Response googleapi.RawMessage `json:"response,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Done") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Done") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Operation) MarshalJSON() ([]byte, error) {
	type NoMethod Operation
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// OperationProgress: Encapsulates progress related information for a Cloud
// Spanner long running operation.
type OperationProgress struct {
	// EndTime: If set, the time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// ProgressPercent: Percent completion of the operation. Values are between 0
	// and 100 inclusive.
	ProgressPercent int64 `json:"progressPercent,omitempty"`
	// StartTime: Time the request was received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EndTime") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EndTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s OperationProgress) MarshalJSON() ([]byte, error) {
	type NoMethod OperationProgress
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// OptimizeRestoredDatabaseMetadata: Metadata type for the long-running
// operation used to track the progress of optimizations performed on a newly
// restored database. This long-running operation is automatically created by
// the system after the successful completion of a database restore, and cannot
// be cancelled.
type OptimizeRestoredDatabaseMetadata struct {
	// Name: Name of the restored database being optimized.
	Name string `json:"name,omitempty"`
	// Progress: The progress of the post-restore optimizations.
	Progress *OperationProgress `json:"progress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Name") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Name") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s OptimizeRestoredDatabaseMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod OptimizeRestoredDatabaseMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartialResultSet: Partial results from a streaming read or SQL query.
// Streaming reads and SQL queries better tolerate large result sets, large
// rows, and large values, but are a little trickier to consume.
type PartialResultSet struct {
	// ChunkedValue: If true, then the final value in values is chunked, and must
	// be combined with more values from subsequent `PartialResultSet`s to obtain a
	// complete field value.
	ChunkedValue bool `json:"chunkedValue,omitempty"`
	// Last: Optional. Indicates whether this is the last `PartialResultSet` in the
	// stream. The server might optionally set this field. Clients shouldn't rely
	// on this field being set in all cases.
	Last bool `json:"last,omitempty"`
	// Metadata: Metadata about the result set, such as row type information. Only
	// present in the first response.
	Metadata *ResultSetMetadata `json:"metadata,omitempty"`
	// PrecommitToken: Optional. A precommit token is included if the read-write
	// transaction has multiplexed sessions enabled. Pass the precommit token with
	// the highest sequence number from this transaction attempt to the Commit
	// request for this transaction.
	PrecommitToken *MultiplexedSessionPrecommitToken `json:"precommitToken,omitempty"`
	// ResumeToken: Streaming calls might be interrupted for a variety of reasons,
	// such as TCP connection loss. If this occurs, the stream of results can be
	// resumed by re-sending the original request and including `resume_token`.
	// Note that executing any other transaction in the same session invalidates
	// the token.
	ResumeToken string `json:"resumeToken,omitempty"`
	// Stats: Query plan and execution statistics for the statement that produced
	// this streaming result set. These can be requested by setting
	// ExecuteSqlRequest.query_mode and are sent only once with the last response
	// in the stream. This field is also present in the last response for DML
	// statements.
	Stats *ResultSetStats `json:"stats,omitempty"`
	// Values: A streamed result set consists of a stream of values, which might be
	// split into many `PartialResultSet` messages to accommodate large rows and/or
	// large values. Every N complete values defines a row, where N is equal to the
	// number of entries in metadata.row_type.fields. Most values are encoded based
	// on type as described here. It's possible that the last value in values is
	// "chunked", meaning that the rest of the value is sent in subsequent
	// `PartialResultSet`(s). This is denoted by the chunked_value field. Two or
	// more chunked values can be merged to form a complete value as follows: *
	// `bool/number/null`: can't be chunked * `string`: concatenate the strings *
	// `list`: concatenate the lists. If the last element in a list is a `string`,
	// `list`, or `object`, merge it with the first element in the next list by
	// applying these rules recursively. * `object`: concatenate the (field name,
	// field value) pairs. If a field name is duplicated, then apply these rules
	// recursively to merge the field values. Some examples of merging: Strings are
	// concatenated. "foo", "bar" => "foobar" Lists of non-strings are
	// concatenated. [2, 3], [4] => [2, 3, 4] Lists are concatenated, but the last
	// and first elements are merged because they are strings. ["a", "b"], ["c",
	// "d"] => ["a", "bc", "d"] Lists are concatenated, but the last and first
	// elements are merged because they are lists. Recursively, the last and first
	// elements of the inner lists are merged because they are strings. ["a", ["b",
	// "c"]], [["d"], "e"] => ["a", ["b", "cd"], "e"] Non-overlapping object fields
	// are combined. {"a": "1"}, {"b": "2"} => {"a": "1", "b": 2"} Overlapping
	// object fields are merged. {"a": "1"}, {"a": "2"} => {"a": "12"} Examples of
	// merging objects containing lists of strings. {"a": ["1"]}, {"a": ["2"]} =>
	// {"a": ["12"]} For a more complete example, suppose a streaming SQL query is
	// yielding a result set whose rows contain a single string field. The
	// following `PartialResultSet`s might be yielded: { "metadata": { ... }
	// "values": ["Hello", "W"] "chunked_value": true "resume_token": "Af65..." } {
	// "values": ["orl"] "chunked_value": true } { "values": ["d"] "resume_token":
	// "Zx1B..." } This sequence of `PartialResultSet`s encodes two rows, one
	// containing the field value "Hello", and a second containing the field
	// value "World" = "W" + "orl" + "d". Not all `PartialResultSet`s contain a
	// `resume_token`. Execution can only be resumed from a previously yielded
	// `resume_token`. For the above sequence of `PartialResultSet`s, resuming the
	// query with "resume_token": "Af65..." yields results from the
	// `PartialResultSet` with value "orl".
	Values []interface{} `json:"values,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ChunkedValue") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ChunkedValue") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartialResultSet) MarshalJSON() ([]byte, error) {
	type NoMethod PartialResultSet
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Partition: Information returned for each partition returned in a
// PartitionResponse.
type Partition struct {
	// PartitionToken: This token can be passed to `Read`, `StreamingRead`,
	// `ExecuteSql`, or `ExecuteStreamingSql` requests to restrict the results to
	// those identified by this partition token.
	PartitionToken string `json:"partitionToken,omitempty"`
	// ForceSendFields is a list of field names (e.g. "PartitionToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "PartitionToken") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Partition) MarshalJSON() ([]byte, error) {
	type NoMethod Partition
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionEndRecord: A partition end record serves as a notification that the
// client should stop reading the partition. No further records are expected to
// be retrieved on it.
type PartitionEndRecord struct {
	// EndTimestamp: End timestamp at which the change stream partition is
	// terminated. All changes generated by this partition will have timestamps <=
	// end_timestamp. DataChangeRecord.commit_timestamps,
	// PartitionStartRecord.start_timestamps,
	// PartitionEventRecord.commit_timestamps, and
	// PartitionEndRecord.end_timestamps can have the same value in the same
	// partition. PartitionEndRecord is the last record returned for a partition.
	EndTimestamp string `json:"endTimestamp,omitempty"`
	// PartitionToken: Unique partition identifier describing the terminated change
	// stream partition. partition_token is equal to the partition token of the
	// change stream partition currently queried to return this PartitionEndRecord.
	PartitionToken string `json:"partitionToken,omitempty"`
	// RecordSequence: Record sequence numbers are unique and monotonically
	// increasing (but not necessarily contiguous) for a specific timestamp across
	// record types in the same partition. To guarantee ordered processing, the
	// reader should process records (of potentially different types) in
	// record_sequence order for a specific timestamp in the same partition.
	RecordSequence string `json:"recordSequence,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EndTimestamp") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EndTimestamp") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionEndRecord) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionEndRecord
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionEventRecord: A partition event record describes key range changes
// for a change stream partition. The changes to a row defined by its primary
// key can be captured in one change stream partition for a specific time
// range, and then be captured in a different change stream partition for a
// different time range. This movement of key ranges across change stream
// partitions is a reflection of activities, such as Spanner's dynamic
// splitting and load balancing, etc. Processing this event is needed if users
// want to guarantee processing of the changes for any key in timestamp order.
// If time ordered processing of changes for a primary key is not needed, this
// event can be ignored. To guarantee time ordered processing for each primary
// key, if the event describes move-ins, the reader of this partition needs to
// wait until the readers of the source partitions have processed all records
// with timestamps <= this PartitionEventRecord.commit_timestamp, before
// advancing beyond this PartitionEventRecord. If the event describes
// move-outs, the reader can notify the readers of the destination partitions
// that they can continue processing.
type PartitionEventRecord struct {
	// CommitTimestamp: Indicates the commit timestamp at which the key range
	// change occurred. DataChangeRecord.commit_timestamps,
	// PartitionStartRecord.start_timestamps,
	// PartitionEventRecord.commit_timestamps, and
	// PartitionEndRecord.end_timestamps can have the same value in the same
	// partition.
	CommitTimestamp string `json:"commitTimestamp,omitempty"`
	// MoveInEvents: Set when one or more key ranges are moved into the change
	// stream partition identified by partition_token. Example: Two key ranges are
	// moved into partition (P1) from partition (P2) and partition (P3) in a single
	// transaction at timestamp T. The PartitionEventRecord returned in P1 will
	// reflect the move as: PartitionEventRecord { commit_timestamp: T
	// partition_token: "P1" move_in_events { source_partition_token: "P2" }
	// move_in_events { source_partition_token: "P3" } } The PartitionEventRecord
	// returned in P2 will reflect the move as: PartitionEventRecord {
	// commit_timestamp: T partition_token: "P2" move_out_events {
	// destination_partition_token: "P1" } } The PartitionEventRecord returned in
	// P3 will reflect the move as: PartitionEventRecord { commit_timestamp: T
	// partition_token: "P3" move_out_events { destination_partition_token: "P1" }
	// }
	MoveInEvents []*MoveInEvent `json:"moveInEvents,omitempty"`
	// MoveOutEvents: Set when one or more key ranges are moved out of the change
	// stream partition identified by partition_token. Example: Two key ranges are
	// moved out of partition (P1) to partition (P2) and partition (P3) in a single
	// transaction at timestamp T. The PartitionEventRecord returned in P1 will
	// reflect the move as: PartitionEventRecord { commit_timestamp: T
	// partition_token: "P1" move_out_events { destination_partition_token: "P2" }
	// move_out_events { destination_partition_token: "P3" } } The
	// PartitionEventRecord returned in P2 will reflect the move as:
	// PartitionEventRecord { commit_timestamp: T partition_token: "P2"
	// move_in_events { source_partition_token: "P1" } } The PartitionEventRecord
	// returned in P3 will reflect the move as: PartitionEventRecord {
	// commit_timestamp: T partition_token: "P3" move_in_events {
	// source_partition_token: "P1" } }
	MoveOutEvents []*MoveOutEvent `json:"moveOutEvents,omitempty"`
	// PartitionToken: Unique partition identifier describing the partition this
	// event occurred on. partition_token is equal to the partition token of the
	// change stream partition currently queried to return this
	// PartitionEventRecord.
	PartitionToken string `json:"partitionToken,omitempty"`
	// RecordSequence: Record sequence numbers are unique and monotonically
	// increasing (but not necessarily contiguous) for a specific timestamp across
	// record types in the same partition. To guarantee ordered processing, the
	// reader should process records (of potentially different types) in
	// record_sequence order for a specific timestamp in the same partition.
	RecordSequence string `json:"recordSequence,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CommitTimestamp") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CommitTimestamp") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionEventRecord) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionEventRecord
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionOptions: Options for a `PartitionQueryRequest` and
// `PartitionReadRequest`.
type PartitionOptions struct {
	// MaxPartitions: **Note:** This hint is currently ignored by `PartitionQuery`
	// and `PartitionRead` requests. The desired maximum number of partitions to
	// return. For example, this might be set to the number of workers available.
	// The default for this option is currently 10,000. The maximum value is
	// currently 200,000. This is only a hint. The actual number of partitions
	// returned can be smaller or larger than this maximum count request.
	MaxPartitions int64 `json:"maxPartitions,omitempty,string"`
	// PartitionSizeBytes: **Note:** This hint is currently ignored by
	// `PartitionQuery` and `PartitionRead` requests. The desired data size for
	// each partition generated. The default for this option is currently 1 GiB.
	// This is only a hint. The actual size of each partition can be smaller or
	// larger than this size request.
	PartitionSizeBytes int64 `json:"partitionSizeBytes,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "MaxPartitions") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "MaxPartitions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionOptions) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionQueryRequest: The request for PartitionQuery
type PartitionQueryRequest struct {
	// ParamTypes: Optional. It isn't always possible for Cloud Spanner to infer
	// the right SQL type from a JSON value. For example, values of type `BYTES`
	// and values of type `STRING` both appear in params as JSON strings. In these
	// cases, `param_types` can be used to specify the exact SQL type for some or
	// all of the SQL query parameters. See the definition of Type for more
	// information about SQL types.
	ParamTypes map[string]Type `json:"paramTypes,omitempty"`
	// Params: Optional. Parameter names and values that bind to placeholders in
	// the SQL string. A parameter placeholder consists of the `@` character
	// followed by the parameter name (for example, `@firstName`). Parameter names
	// can contain letters, numbers, and underscores. Parameters can appear
	// anywhere that a literal value is expected. The same parameter name can be
	// used more than once, for example: "WHERE id > @msg_id AND id < @msg_id +
	// 100" It's an error to execute a SQL statement with unbound parameters.
	Params googleapi.RawMessage `json:"params,omitempty"`
	// PartitionOptions: Additional options that affect how many partitions are
	// created.
	PartitionOptions *PartitionOptions `json:"partitionOptions,omitempty"`
	// Sql: Required. The query request to generate partitions for. The request
	// fails if the query isn't root partitionable. For a query to be root
	// partitionable, it needs to satisfy a few conditions. For example, if the
	// query execution plan contains a distributed union operator, then it must be
	// the first operator in the plan. For more information about other conditions,
	// see Read data in parallel
	// (https://cloud.google.com/spanner/docs/reads#read_data_in_parallel). The
	// query request must not contain DML commands, such as `INSERT`, `UPDATE`, or
	// `DELETE`. Use `ExecuteStreamingSql` with a `PartitionedDml` transaction for
	// large, partition-friendly DML operations.
	Sql string `json:"sql,omitempty"`
	// Transaction: Read-only snapshot transactions are supported, read and write
	// and single-use transactions are not.
	Transaction *TransactionSelector `json:"transaction,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ParamTypes") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ParamTypes") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionQueryRequest) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionQueryRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionReadRequest: The request for PartitionRead
type PartitionReadRequest struct {
	// Columns: The columns of table to be returned for each row matching this
	// request.
	Columns []string `json:"columns,omitempty"`
	// Index: If non-empty, the name of an index on table. This index is used
	// instead of the table primary key when interpreting key_set and sorting
	// result rows. See key_set for further information.
	Index string `json:"index,omitempty"`
	// KeySet: Required. `key_set` identifies the rows to be yielded. `key_set`
	// names the primary keys of the rows in table to be yielded, unless index is
	// present. If index is present, then key_set instead names index keys in
	// index. It isn't an error for the `key_set` to name rows that don't exist in
	// the database. Read yields nothing for nonexistent rows.
	KeySet *KeySet `json:"keySet,omitempty"`
	// PartitionOptions: Additional options that affect how many partitions are
	// created.
	PartitionOptions *PartitionOptions `json:"partitionOptions,omitempty"`
	// Table: Required. The name of the table in the database to be read.
	Table string `json:"table,omitempty"`
	// Transaction: Read only snapshot transactions are supported, read/write and
	// single use transactions are not.
	Transaction *TransactionSelector `json:"transaction,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Columns") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Columns") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionReadRequest) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionReadRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionResponse: The response for PartitionQuery or PartitionRead
type PartitionResponse struct {
	// Partitions: Partitions created by this request.
	Partitions []*Partition `json:"partitions,omitempty"`
	// Transaction: Transaction created by this request.
	Transaction *Transaction `json:"transaction,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Partitions") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Partitions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionResponse) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionStartRecord: A partition start record serves as a notification that
// the client should schedule the partitions to be queried.
// PartitionStartRecord returns information about one or more partitions.
type PartitionStartRecord struct {
	// PartitionTokens: Unique partition identifiers to be used in queries.
	PartitionTokens []string `json:"partitionTokens,omitempty"`
	// RecordSequence: Record sequence numbers are unique and monotonically
	// increasing (but not necessarily contiguous) for a specific timestamp across
	// record types in the same partition. To guarantee ordered processing, the
	// reader should process records (of potentially different types) in
	// record_sequence order for a specific timestamp in the same partition.
	RecordSequence string `json:"recordSequence,omitempty"`
	// StartTimestamp: Start timestamp at which the partitions should be queried to
	// return change stream records with timestamps >= start_timestamp.
	// DataChangeRecord.commit_timestamps, PartitionStartRecord.start_timestamps,
	// PartitionEventRecord.commit_timestamps, and
	// PartitionEndRecord.end_timestamps can have the same value in the same
	// partition.
	StartTimestamp string `json:"startTimestamp,omitempty"`
	// ForceSendFields is a list of field names (e.g. "PartitionTokens") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "PartitionTokens") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PartitionStartRecord) MarshalJSON() ([]byte, error) {
	type NoMethod PartitionStartRecord
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PartitionedDml: Message type to initiate a Partitioned DML transaction.
type PartitionedDml struct {
}

// PlanNode: Node information for nodes appearing in a QueryPlan.plan_nodes.
type PlanNode struct {
	// ChildLinks: List of child node `index`es and their relationship to this
	// parent.
	ChildLinks []*ChildLink `json:"childLinks,omitempty"`
	// DisplayName: The display name for the node.
	DisplayName string `json:"displayName,omitempty"`
	// ExecutionStats: The execution statistics associated with the node, contained
	// in a group of key-value pairs. Only present if the plan was returned as a
	// result of a profile query. For example, number of executions, number of
	// rows/time per execution etc.
	ExecutionStats googleapi.RawMessage `json:"executionStats,omitempty"`
	// Index: The `PlanNode`'s index in node list.
	Index int64 `json:"index,omitempty"`
	// Kind: Used to determine the type of node. May be needed for visualizing
	// different kinds of nodes differently. For example, If the node is a SCALAR
	// node, it will have a condensed representation which can be used to directly
	// embed a description of the node in its parent.
	//
	// Possible values:
	//   "KIND_UNSPECIFIED" - Not specified.
	//   "RELATIONAL" - Denotes a Relational operator node in the expression tree.
	// Relational operators represent iterative processing of rows during query
	// execution. For example, a `TableScan` operation that reads rows from a
	// table.
	//   "SCALAR" - Denotes a Scalar node in the expression tree. Scalar nodes
	// represent non-iterable entities in the query plan. For example, constants or
	// arithmetic operators appearing inside predicate expressions or references to
	// column names.
	Kind string `json:"kind,omitempty"`
	// Metadata: Attributes relevant to the node contained in a group of key-value
	// pairs. For example, a Parameter Reference node could have the following
	// information in its metadata: { "parameter_reference": "param1",
	// "parameter_type": "array" }
	Metadata googleapi.RawMessage `json:"metadata,omitempty"`
	// ShortRepresentation: Condensed representation for SCALAR nodes.
	ShortRepresentation *ShortRepresentation `json:"shortRepresentation,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ChildLinks") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ChildLinks") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PlanNode) MarshalJSON() ([]byte, error) {
	type NoMethod PlanNode
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Policy: An Identity and Access Management (IAM) policy, which specifies
// access controls for Google Cloud resources. A `Policy` is a collection of
// `bindings`. A `binding` binds one or more `members`, or principals, to a
// single `role`. Principals can be user accounts, service accounts, Google
// groups, and domains (such as G Suite). A `role` is a named list of
// permissions; each `role` can be an IAM predefined role or a user-created
// custom role. For some types of Google Cloud resources, a `binding` can also
// specify a `condition`, which is a logical expression that allows access to a
// resource only if the expression evaluates to `true`. A condition can add
// constraints based on attributes of the request, the resource, or both. To
// learn which resources support conditions in their IAM policies, see the IAM
// documentation
// (https://cloud.google.com/iam/help/conditions/resource-policies). **JSON
// example:** ``` { "bindings": [ { "role":
// "roles/resourcemanager.organizationAdmin", "members": [
// "user:mike@example.com", "group:admins@example.com", "domain:google.com",
// "serviceAccount:my-project-id@appspot.gserviceaccount.com" ] }, { "role":
// "roles/resourcemanager.organizationViewer", "members": [
// "user:eve@example.com" ], "condition": { "title": "expirable access",
// "description": "Does not grant access after Sep 2020", "expression":
// "request.time < timestamp('2020-10-01T00:00:00.000Z')", } } ], "etag":
// "BwWWja0YfJA=", "version": 3 } ``` **YAML example:** ``` bindings: -
// members: - user:mike@example.com - group:admins@example.com -
// domain:google.com - serviceAccount:my-project-id@appspot.gserviceaccount.com
// role: roles/resourcemanager.organizationAdmin - members: -
// user:eve@example.com role: roles/resourcemanager.organizationViewer
// condition: title: expirable access description: Does not grant access after
// Sep 2020 expression: request.time < timestamp('2020-10-01T00:00:00.000Z')
// etag: BwWWja0YfJA= version: 3 ``` For a description of IAM and its features,
// see the IAM documentation (https://cloud.google.com/iam/docs/).
type Policy struct {
	// Bindings: Associates a list of `members`, or principals, with a `role`.
	// Optionally, may specify a `condition` that determines how and when the
	// `bindings` are applied. Each of the `bindings` must contain at least one
	// principal. The `bindings` in a `Policy` can refer to up to 1,500 principals;
	// up to 250 of these principals can be Google groups. Each occurrence of a
	// principal counts towards these limits. For example, if the `bindings` grant
	// 50 different roles to `user:alice@example.com`, and not to any other
	// principal, then you can add another 1,450 principals to the `bindings` in
	// the `Policy`.
	Bindings []*Binding `json:"bindings,omitempty"`
	// Etag: `etag` is used for optimistic concurrency control as a way to help
	// prevent simultaneous updates of a policy from overwriting each other. It is
	// strongly suggested that systems make use of the `etag` in the
	// read-modify-write cycle to perform policy updates in order to avoid race
	// conditions: An `etag` is returned in the response to `getIamPolicy`, and
	// systems are expected to put that etag in the request to `setIamPolicy` to
	// ensure that their change will be applied to the same version of the policy.
	// **Important:** If you use IAM Conditions, you must include the `etag` field
	// whenever you call `setIamPolicy`. If you omit this field, then IAM allows
	// you to overwrite a version `3` policy with a version `1` policy, and all of
	// the conditions in the version `3` policy are lost.
	Etag string `json:"etag,omitempty"`
	// Version: Specifies the format of the policy. Valid values are `0`, `1`, and
	// `3`. Requests that specify an invalid value are rejected. Any operation that
	// affects conditional role bindings must specify version `3`. This requirement
	// applies to the following operations: * Getting a policy that includes a
	// conditional role binding * Adding a conditional role binding to a policy *
	// Changing a conditional role binding in a policy * Removing any role binding,
	// with or without a condition, from a policy that includes conditions
	// **Important:** If you use IAM Conditions, you must include the `etag` field
	// whenever you call `setIamPolicy`. If you omit this field, then IAM allows
	// you to overwrite a version `3` policy with a version `1` policy, and all of
	// the conditions in the version `3` policy are lost. If a policy does not
	// include any conditions, operations on that policy may specify any valid
	// version or leave the field unset. To learn which resources support
	// conditions in their IAM policies, see the IAM documentation
	// (https://cloud.google.com/iam/help/conditions/resource-policies).
	Version int64 `json:"version,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Bindings") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Bindings") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Policy) MarshalJSON() ([]byte, error) {
	type NoMethod Policy
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// PrefixNode: A message representing a key prefix node in the key prefix
// hierarchy. for eg. Bigtable keyspaces are lexicographically ordered mappings
// of keys to values. Keys often have a shared prefix structure where users use
// the keys to organize data. Eg ///employee In this case Keysight will
// possibly use one node for a company and reuse it for all employees that fall
// under the company. Doing so improves legibility in the UI.
type PrefixNode struct {
	// DataSourceNode: Whether this corresponds to a data_source name.
	DataSourceNode bool `json:"dataSourceNode,omitempty"`
	// Depth: The depth in the prefix hierarchy.
	Depth int64 `json:"depth,omitempty"`
	// EndIndex: The index of the end key bucket of the range that this node spans.
	EndIndex int64 `json:"endIndex,omitempty"`
	// StartIndex: The index of the start key bucket of the range that this node
	// spans.
	StartIndex int64 `json:"startIndex,omitempty"`
	// Word: The string represented by the prefix node.
	Word string `json:"word,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DataSourceNode") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DataSourceNode") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s PrefixNode) MarshalJSON() ([]byte, error) {
	type NoMethod PrefixNode
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// QueryAdvisorResult: Output of query advisor analysis.
type QueryAdvisorResult struct {
	// IndexAdvice: Optional. Index Recommendation for a query. This is an optional
	// field and the recommendation will only be available when the recommendation
	// guarantees significant improvement in query performance.
	IndexAdvice []*IndexAdvice `json:"indexAdvice,omitempty"`
	// ForceSendFields is a list of field names (e.g. "IndexAdvice") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "IndexAdvice") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s QueryAdvisorResult) MarshalJSON() ([]byte, error) {
	type NoMethod QueryAdvisorResult
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// QueryOptions: Query optimizer configuration.
type QueryOptions struct {
	// OptimizerStatisticsPackage: An option to control the selection of optimizer
	// statistics package. This parameter allows individual queries to use a
	// different query optimizer statistics package. Specifying `latest` as a value
	// instructs Cloud Spanner to use the latest generated statistics package. If
	// not specified, Cloud Spanner uses the statistics package set at the database
	// level options, or the latest package if the database option isn't set. The
	// statistics package requested by the query has to be exempt from garbage
	// collection. This can be achieved with the following DDL statement: ```sql
	// ALTER STATISTICS SET OPTIONS (allow_gc=false) ``` The list of available
	// statistics packages can be queried from
	// `INFORMATION_SCHEMA.SPANNER_STATISTICS`. Executing a SQL statement with an
	// invalid optimizer statistics package or with a statistics package that
	// allows garbage collection fails with an `INVALID_ARGUMENT` error.
	OptimizerStatisticsPackage string `json:"optimizerStatisticsPackage,omitempty"`
	// OptimizerVersion: An option to control the selection of optimizer version.
	// This parameter allows individual queries to pick different query optimizer
	// versions. Specifying `latest` as a value instructs Cloud Spanner to use the
	// latest supported query optimizer version. If not specified, Cloud Spanner
	// uses the optimizer version set at the database level options. Any other
	// positive integer (from the list of supported optimizer versions) overrides
	// the default optimizer version for query execution. The list of supported
	// optimizer versions can be queried from
	// `SPANNER_SYS.SUPPORTED_OPTIMIZER_VERSIONS`. Executing a SQL statement with
	// an invalid optimizer version fails with an `INVALID_ARGUMENT` error. See
	// https://cloud.google.com/spanner/docs/query-optimizer/manage-query-optimizer
	// for more information on managing the query optimizer. The
	// `optimizer_version` statement hint has precedence over this setting.
	OptimizerVersion string `json:"optimizerVersion,omitempty"`
	// ForceSendFields is a list of field names (e.g. "OptimizerStatisticsPackage")
	// to unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "OptimizerStatisticsPackage") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s QueryOptions) MarshalJSON() ([]byte, error) {
	type NoMethod QueryOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// QueryPlan: Contains an ordered list of nodes appearing in the query plan.
type QueryPlan struct {
	// PlanNodes: The nodes in the query plan. Plan nodes are returned in pre-order
	// starting with the plan root. Each PlanNode's `id` corresponds to its index
	// in `plan_nodes`.
	PlanNodes []*PlanNode `json:"planNodes,omitempty"`
	// QueryAdvice: Optional. The advise/recommendations for a query. Currently
	// this field will be serving index recommendations for a query.
	QueryAdvice *QueryAdvisorResult `json:"queryAdvice,omitempty"`
	// ForceSendFields is a list of field names (e.g. "PlanNodes") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "PlanNodes") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s QueryPlan) MarshalJSON() ([]byte, error) {
	type NoMethod QueryPlan
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// QuorumInfo: Information about the dual-region quorum.
type QuorumInfo struct {
	// Etag: Output only. The etag is used for optimistic concurrency control as a
	// way to help prevent simultaneous `ChangeQuorum` requests that might create a
	// race condition.
	Etag string `json:"etag,omitempty"`
	// Initiator: Output only. Whether this `ChangeQuorum` is Google or User
	// initiated.
	//
	// Possible values:
	//   "INITIATOR_UNSPECIFIED" - Unspecified.
	//   "GOOGLE" - `ChangeQuorum` initiated by Google.
	//   "USER" - `ChangeQuorum` initiated by User.
	Initiator string `json:"initiator,omitempty"`
	// QuorumType: Output only. The type of this quorum. See QuorumType for more
	// information about quorum type specifications.
	QuorumType *QuorumType `json:"quorumType,omitempty"`
	// StartTime: Output only. The timestamp when the request was triggered.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Etag") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Etag") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s QuorumInfo) MarshalJSON() ([]byte, error) {
	type NoMethod QuorumInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// QuorumType: Information about the database quorum type. This only applies to
// dual-region instance configs.
type QuorumType struct {
	// DualRegion: Dual-region quorum type.
	DualRegion *DualRegionQuorum `json:"dualRegion,omitempty"`
	// SingleRegion: Single-region quorum type.
	SingleRegion *SingleRegionQuorum `json:"singleRegion,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DualRegion") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DualRegion") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s QuorumType) MarshalJSON() ([]byte, error) {
	type NoMethod QuorumType
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ReadOnly: Message type to initiate a read-only transaction.
type ReadOnly struct {
	// ExactStaleness: Executes all reads at a timestamp that is `exact_staleness`
	// old. The timestamp is chosen soon after the read is started. Guarantees that
	// all writes that have committed more than the specified number of seconds ago
	// are visible. Because Cloud Spanner chooses the exact timestamp, this mode
	// works even if the client's local clock is substantially skewed from Cloud
	// Spanner commit timestamps. Useful for reading at nearby replicas without the
	// distributed timestamp negotiation overhead of `max_staleness`.
	ExactStaleness string `json:"exactStaleness,omitempty"`
	// MaxStaleness: Read data at a timestamp >= `NOW - max_staleness` seconds.
	// Guarantees that all writes that have committed more than the specified
	// number of seconds ago are visible. Because Cloud Spanner chooses the exact
	// timestamp, this mode works even if the client's local clock is substantially
	// skewed from Cloud Spanner commit timestamps. Useful for reading the freshest
	// data available at a nearby replica, while bounding the possible staleness if
	// the local replica has fallen behind. Note that this option can only be used
	// in single-use transactions.
	MaxStaleness string `json:"maxStaleness,omitempty"`
	// MinReadTimestamp: Executes all reads at a timestamp >= `min_read_timestamp`.
	// This is useful for requesting fresher data than some previous read, or data
	// that is fresh enough to observe the effects of some previously committed
	// transaction whose timestamp is known. Note that this option can only be used
	// in single-use transactions. A timestamp in RFC3339 UTC \"Zulu\" format,
	// accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z".
	MinReadTimestamp string `json:"minReadTimestamp,omitempty"`
	// ReadTimestamp: Executes all reads at the given timestamp. Unlike other
	// modes, reads at a specific timestamp are repeatable; the same read at the
	// same timestamp always returns the same data. If the timestamp is in the
	// future, the read is blocked until the specified timestamp, modulo the read's
	// deadline. Useful for large scale consistent reads such as mapreduces, or for
	// coordinating many reads against a consistent snapshot of the data. A
	// timestamp in RFC3339 UTC \"Zulu\" format, accurate to nanoseconds. Example:
	// "2014-10-02T15:01:23.045123456Z".
	ReadTimestamp string `json:"readTimestamp,omitempty"`
	// ReturnReadTimestamp: If true, the Cloud Spanner-selected read timestamp is
	// included in the Transaction message that describes the transaction.
	ReturnReadTimestamp bool `json:"returnReadTimestamp,omitempty"`
	// Strong: Read at a timestamp where all previously committed transactions are
	// visible.
	Strong bool `json:"strong,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExactStaleness") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExactStaleness") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ReadOnly) MarshalJSON() ([]byte, error) {
	type NoMethod ReadOnly
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ReadRequest: The request for Read and StreamingRead.
type ReadRequest struct {
	// Columns: Required. The columns of table to be returned for each row matching
	// this request.
	Columns []string `json:"columns,omitempty"`
	// DataBoostEnabled: If this is for a partitioned read and this field is set to
	// `true`, the request is executed with Spanner Data Boost independent compute
	// resources. If the field is set to `true` but the request doesn't set
	// `partition_token`, the API returns an `INVALID_ARGUMENT` error.
	DataBoostEnabled bool `json:"dataBoostEnabled,omitempty"`
	// DirectedReadOptions: Directed read options for this request.
	DirectedReadOptions *DirectedReadOptions `json:"directedReadOptions,omitempty"`
	// Index: If non-empty, the name of an index on table. This index is used
	// instead of the table primary key when interpreting key_set and sorting
	// result rows. See key_set for further information.
	Index string `json:"index,omitempty"`
	// KeySet: Required. `key_set` identifies the rows to be yielded. `key_set`
	// names the primary keys of the rows in table to be yielded, unless index is
	// present. If index is present, then key_set instead names index keys in
	// index. If the partition_token field is empty, rows are yielded in table
	// primary key order (if index is empty) or index key order (if index is
	// non-empty). If the partition_token field isn't empty, rows are yielded in an
	// unspecified order. It isn't an error for the `key_set` to name rows that
	// don't exist in the database. Read yields nothing for nonexistent rows.
	KeySet *KeySet `json:"keySet,omitempty"`
	// Limit: If greater than zero, only the first `limit` rows are yielded. If
	// `limit` is zero, the default is no limit. A limit can't be specified if
	// `partition_token` is set.
	Limit int64 `json:"limit,omitempty,string"`
	// LockHint: Optional. Lock Hint for the request, it can only be used with
	// read-write transactions.
	//
	// Possible values:
	//   "LOCK_HINT_UNSPECIFIED" - Default value. `LOCK_HINT_UNSPECIFIED` is
	// equivalent to `LOCK_HINT_SHARED`.
	//   "LOCK_HINT_SHARED" - Acquire shared locks. By default when you perform a
	// read as part of a read-write transaction, Spanner acquires shared read
	// locks, which allows other reads to still access the data until your
	// transaction is ready to commit. When your transaction is committing and
	// writes are being applied, the transaction attempts to upgrade to an
	// exclusive lock for any data you are writing. For more information about
	// locks, see [Lock
	// modes](https://cloud.google.com/spanner/docs/introspection/lock-statistics#ex
	// plain-lock-modes).
	//   "LOCK_HINT_EXCLUSIVE" - Acquire exclusive locks. Requesting exclusive
	// locks is beneficial if you observe high write contention, which means you
	// notice that multiple transactions are concurrently trying to read and write
	// to the same data, resulting in a large number of aborts. This problem occurs
	// when two transactions initially acquire shared locks and then both try to
	// upgrade to exclusive locks at the same time. In this situation both
	// transactions are waiting for the other to give up their lock, resulting in a
	// deadlocked situation. Spanner is able to detect this occurring and force one
	// of the transactions to abort. However, this is a slow and expensive
	// operation and results in lower performance. In this case it makes sense to
	// acquire exclusive locks at the start of the transaction because then when
	// multiple transactions try to act on the same data, they automatically get
	// serialized. Each transaction waits its turn to acquire the lock and avoids
	// getting into deadlock situations. Because the exclusive lock hint is just a
	// hint, it shouldn't be considered equivalent to a mutex. In other words, you
	// shouldn't use Spanner exclusive locks as a mutual exclusion mechanism for
	// the execution of code outside of Spanner. **Note:** Request exclusive locks
	// judiciously because they block others from reading that data for the entire
	// transaction, rather than just when the writes are being performed. Unless
	// you observe high write contention, you should use the default of shared read
	// locks so you don't prematurely block other clients from reading the data
	// that you're writing to.
	LockHint string `json:"lockHint,omitempty"`
	// OrderBy: Optional. Order for the returned rows. By default, Spanner returns
	// result rows in primary key order except for PartitionRead requests. For
	// applications that don't require rows to be returned in primary key
	// (`ORDER_BY_PRIMARY_KEY`) order, setting `ORDER_BY_NO_ORDER` option allows
	// Spanner to optimize row retrieval, resulting in lower latencies in certain
	// cases (for example, bulk point lookups).
	//
	// Possible values:
	//   "ORDER_BY_UNSPECIFIED" - Default value. `ORDER_BY_UNSPECIFIED` is
	// equivalent to `ORDER_BY_PRIMARY_KEY`.
	//   "ORDER_BY_PRIMARY_KEY" - Read rows are returned in primary key order. In
	// the event that this option is used in conjunction with the `partition_token`
	// field, the API returns an `INVALID_ARGUMENT` error.
	//   "ORDER_BY_NO_ORDER" - Read rows are returned in any order.
	OrderBy string `json:"orderBy,omitempty"`
	// PartitionToken: If present, results are restricted to the specified
	// partition previously created using `PartitionRead`. There must be an exact
	// match for the values of fields common to this message and the
	// PartitionReadRequest message used to create this partition_token.
	PartitionToken string `json:"partitionToken,omitempty"`
	// RequestOptions: Common options for this request.
	RequestOptions *RequestOptions `json:"requestOptions,omitempty"`
	// ResumeToken: If this request is resuming a previously interrupted read,
	// `resume_token` should be copied from the last PartialResultSet yielded
	// before the interruption. Doing this enables the new read to resume where the
	// last read left off. The rest of the request parameters must exactly match
	// the request that yielded this token.
	ResumeToken string `json:"resumeToken,omitempty"`
	// Table: Required. The name of the table in the database to be read.
	Table string `json:"table,omitempty"`
	// Transaction: The transaction to use. If none is provided, the default is a
	// temporary read-only transaction with strong concurrency.
	Transaction *TransactionSelector `json:"transaction,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Columns") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Columns") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ReadRequest) MarshalJSON() ([]byte, error) {
	type NoMethod ReadRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ReadWrite: Message type to initiate a read-write transaction. Currently this
// transaction type has no options.
type ReadWrite struct {
	// MultiplexedSessionPreviousTransactionId: Optional. Clients should pass the
	// transaction ID of the previous transaction attempt that was aborted if this
	// transaction is being executed on a multiplexed session.
	MultiplexedSessionPreviousTransactionId string `json:"multiplexedSessionPreviousTransactionId,omitempty"`
	// ReadLockMode: The read lock mode for the transaction.
	//
	// Possible values:
	//   "READ_LOCK_MODE_UNSPECIFIED" - Default value. * If isolation level is
	// SERIALIZABLE, locking semantics default to `PESSIMISTIC`. * If isolation
	// level is REPEATABLE_READ, locking semantics default to `OPTIMISTIC`. * See
	// [Concurrency
	// control](https://cloud.google.com/spanner/docs/concurrency-control) for more
	// details.
	//   "PESSIMISTIC" - Pessimistic lock mode. Lock acquisition behavior depends
	// on the isolation level in use. In SERIALIZABLE isolation, reads and writes
	// acquire necessary locks during transaction statement execution. In
	// REPEATABLE_READ isolation, reads that explicitly request to be locked and
	// writes acquire locks. See [Concurrency
	// control](https://cloud.google.com/spanner/docs/concurrency-control) for
	// details on the types of locks acquired at each transaction step.
	//   "OPTIMISTIC" - Optimistic lock mode. Lock acquisition behavior depends on
	// the isolation level in use. In both SERIALIZABLE and REPEATABLE_READ
	// isolation, reads and writes do not acquire locks during transaction
	// statement execution. See [Concurrency
	// control](https://cloud.google.com/spanner/docs/concurrency-control) for
	// details on how the guarantees of each isolation level are provided at commit
	// time.
	ReadLockMode string `json:"readLockMode,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "MultiplexedSessionPreviousTransactionId") to unconditionally include in API
	// requests. By default, fields with empty or default values are omitted from
	// API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g.
	// "MultiplexedSessionPreviousTransactionId") to include in API requests with
	// the JSON null value. By default, fields with empty values are omitted from
	// API requests. See https://pkg.go.dev/google.golang.org/api#hdr-NullFields
	// for more details.
	NullFields []string `json:"-"`
}

func (s ReadWrite) MarshalJSON() ([]byte, error) {
	type NoMethod ReadWrite
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ReplicaComputeCapacity: ReplicaComputeCapacity describes the amount of
// server resources that are allocated to each replica identified by the
// replica selection.
type ReplicaComputeCapacity struct {
	// NodeCount: The number of nodes allocated to each replica. This may be zero
	// in API responses for instances that are not yet in state `READY`.
	NodeCount int64 `json:"nodeCount,omitempty"`
	// ProcessingUnits: The number of processing units allocated to each replica.
	// This may be zero in API responses for instances that are not yet in state
	// `READY`.
	ProcessingUnits int64 `json:"processingUnits,omitempty"`
	// ReplicaSelection: Required. Identifies replicas by specified properties. All
	// replicas in the selection have the same amount of compute capacity.
	ReplicaSelection *InstanceReplicaSelection `json:"replicaSelection,omitempty"`
	// ForceSendFields is a list of field names (e.g. "NodeCount") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "NodeCount") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ReplicaComputeCapacity) MarshalJSON() ([]byte, error) {
	type NoMethod ReplicaComputeCapacity
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

type ReplicaInfo struct {
	// DefaultLeaderLocation: If true, this location is designated as the default
	// leader location where leader replicas are placed. See the region types
	// documentation (https://cloud.google.com/spanner/docs/instances#region_types)
	// for more details.
	DefaultLeaderLocation bool `json:"defaultLeaderLocation,omitempty"`
	// Location: The location of the serving resources, e.g., "us-central1".
	Location string `json:"location,omitempty"`
	// Type: The type of replica.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Not specified.
	//   "READ_WRITE" - Read-write replicas support both reads and writes. These
	// replicas: * Maintain a full copy of your data. * Serve reads. * Can vote
	// whether to commit a write. * Participate in leadership election. * Are
	// eligible to become a leader.
	//   "READ_ONLY" - Read-only replicas only support reads (not writes).
	// Read-only replicas: * Maintain a full copy of your data. * Serve reads. * Do
	// not participate in voting to commit writes. * Are not eligible to become a
	// leader.
	//   "WITNESS" - Witness replicas don't support reads but do participate in
	// voting to commit writes. Witness replicas: * Do not maintain a full copy of
	// data. * Do not serve reads. * Vote whether to commit writes. * Participate
	// in leader election but are not eligible to become leader.
	Type string `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DefaultLeaderLocation") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DefaultLeaderLocation") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ReplicaInfo) MarshalJSON() ([]byte, error) {
	type NoMethod ReplicaInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ReplicaSelection: The directed read replica selector. Callers must provide
// one or more of the following fields for replica selection: * `location` -
// The location must be one of the regions within the multi-region
// configuration of your database. * `type` - The type of the replica. Some
// examples of using replica_selectors are: * `location:us-east1` --> The
// "us-east1" replica(s) of any available type is used to process the request.
// * `type:READ_ONLY` --> The "READ_ONLY" type replica(s) in the nearest
// available location are used to process the request. * `location:us-east1
// type:READ_ONLY` --> The "READ_ONLY" type replica(s) in location "us-east1"
// is used to process the request.
type ReplicaSelection struct {
	// Location: The location or region of the serving requests, for example,
	// "us-east1".
	Location string `json:"location,omitempty"`
	// Type: The type of replica.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Not specified.
	//   "READ_WRITE" - Read-write replicas support both reads and writes.
	//   "READ_ONLY" - Read-only replicas only support reads (not writes).
	Type string `json:"type,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Location") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Location") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ReplicaSelection) MarshalJSON() ([]byte, error) {
	type NoMethod ReplicaSelection
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RequestOptions: Common request options for various APIs.
type RequestOptions struct {
	// ClientContext: Optional. Optional context that may be needed for some
	// requests.
	ClientContext *ClientContext `json:"clientContext,omitempty"`
	// Priority: Priority for the request.
	//
	// Possible values:
	//   "PRIORITY_UNSPECIFIED" - `PRIORITY_UNSPECIFIED` is equivalent to
	// `PRIORITY_HIGH`.
	//   "PRIORITY_LOW" - This specifies that the request is low priority.
	//   "PRIORITY_MEDIUM" - This specifies that the request is medium priority.
	//   "PRIORITY_HIGH" - This specifies that the request is high priority.
	Priority string `json:"priority,omitempty"`
	// RequestTag: A per-request tag which can be applied to queries or reads, used
	// for statistics collection. Both `request_tag` and `transaction_tag` can be
	// specified for a read or query that belongs to a transaction. This field is
	// ignored for requests where it's not applicable (for example,
	// `CommitRequest`). Legal characters for `request_tag` values are all
	// printable characters (ASCII 32 - 126) and the length of a request_tag is
	// limited to 50 characters. Values that exceed this limit are truncated. Any
	// leading underscore (_) characters are removed from the string.
	RequestTag string `json:"requestTag,omitempty"`
	// TransactionTag: A tag used for statistics collection about this transaction.
	// Both `request_tag` and `transaction_tag` can be specified for a read or
	// query that belongs to a transaction. To enable tagging on a transaction,
	// `transaction_tag` must be set to the same value for all requests belonging
	// to the same transaction, including BeginTransaction. If this request doesn't
	// belong to any transaction, `transaction_tag` is ignored. Legal characters
	// for `transaction_tag` values are all printable characters (ASCII 32 - 126)
	// and the length of a `transaction_tag` is limited to 50 characters. Values
	// that exceed this limit are truncated. Any leading underscore (_) characters
	// are removed from the string.
	TransactionTag string `json:"transactionTag,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ClientContext") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ClientContext") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s RequestOptions) MarshalJSON() ([]byte, error) {
	type NoMethod RequestOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RestoreDatabaseEncryptionConfig: Encryption configuration for the restored
// database.
type RestoreDatabaseEncryptionConfig struct {
	// EncryptionType: Required. The encryption type of the restored database.
	//
	// Possible values:
	//   "ENCRYPTION_TYPE_UNSPECIFIED" - Unspecified. Do not use.
	//   "USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION" - This is the default option
	// when encryption_config is not specified.
	//   "GOOGLE_DEFAULT_ENCRYPTION" - Use Google default encryption.
	//   "CUSTOMER_MANAGED_ENCRYPTION" - Use customer managed encryption. If
	// specified, `kms_key_name` must must contain a valid Cloud KMS key.
	EncryptionType string `json:"encryptionType,omitempty"`
	// KmsKeyName: Optional. This field is maintained for backwards compatibility.
	// For new callers, we recommend using `kms_key_names` to specify the KMS key.
	// Only use `kms_key_name` if the location of the KMS key matches the database
	// instance's configuration (location) exactly. For example, if the KMS
	// location is in `us-central1` or `nam3`, then the database instance must also
	// be in `us-central1` or `nam3`. The Cloud KMS key that is used to encrypt and
	// decrypt the restored database. Set this field only when encryption_type is
	// `CUSTOMER_MANAGED_ENCRYPTION`. Values are of the form
	// `projects//locations//keyRings//cryptoKeys/`.
	KmsKeyName string `json:"kmsKeyName,omitempty"`
	// KmsKeyNames: Optional. Specifies the KMS configuration for one or more keys
	// used to encrypt the database. Values have the form
	// `projects//locations//keyRings//cryptoKeys/`. The keys referenced by
	// `kms_key_names` must fully cover all regions of the database's instance
	// configuration. Some examples: * For regional (single-region) instance
	// configurations, specify a regional location KMS key. * For multi-region
	// instance configurations of type `GOOGLE_MANAGED`, either specify a
	// multi-region location KMS key or multiple regional location KMS keys that
	// cover all regions in the instance configuration. * For an instance
	// configuration of type `USER_MANAGED`, specify only regional location KMS
	// keys to cover each region in the instance configuration. Multi-region
	// location KMS keys aren't supported for `USER_MANAGED` type instance
	// configurations.
	KmsKeyNames []string `json:"kmsKeyNames,omitempty"`
	// ForceSendFields is a list of field names (e.g. "EncryptionType") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "EncryptionType") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s RestoreDatabaseEncryptionConfig) MarshalJSON() ([]byte, error) {
	type NoMethod RestoreDatabaseEncryptionConfig
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RestoreDatabaseMetadata: Metadata type for the long-running operation
// returned by RestoreDatabase.
type RestoreDatabaseMetadata struct {
	// BackupInfo: Information about the backup used to restore the database.
	BackupInfo *BackupInfo `json:"backupInfo,omitempty"`
	// CancelTime: The time at which cancellation of this operation was received.
	// Operations.CancelOperation starts asynchronous cancellation on a
	// long-running operation. The server makes a best effort to cancel the
	// operation, but success is not guaranteed. Clients can use
	// Operations.GetOperation or other methods to check whether the cancellation
	// succeeded or whether the operation completed despite cancellation. On
	// successful cancellation, the operation is not deleted; instead, it becomes
	// an operation with an Operation.error value with a google.rpc.Status.code of
	// 1, corresponding to `Code.CANCELLED`.
	CancelTime string `json:"cancelTime,omitempty"`
	// Name: Name of the database being created and restored to.
	Name string `json:"name,omitempty"`
	// OptimizeDatabaseOperationName: If exists, the name of the long-running
	// operation that will be used to track the post-restore optimization process
	// to optimize the performance of the restored database, and remove the
	// dependency on the restore source. The name is of the form
	// `projects//instances//databases//operations/` where the is the name of
	// database being created and restored to. The metadata type of the
	// long-running operation is OptimizeRestoredDatabaseMetadata. This
	// long-running operation will be automatically created by the system after the
	// RestoreDatabase long-running operation completes successfully. This
	// operation will not be created if the restore was not successful.
	OptimizeDatabaseOperationName string `json:"optimizeDatabaseOperationName,omitempty"`
	// Progress: The progress of the RestoreDatabase operation.
	Progress *OperationProgress `json:"progress,omitempty"`
	// SourceType: The type of the restore source.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - No restore associated.
	//   "BACKUP" - A backup was used as the source of the restore.
	SourceType string `json:"sourceType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BackupInfo") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BackupInfo") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s RestoreDatabaseMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod RestoreDatabaseMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RestoreDatabaseRequest: The request for RestoreDatabase.
type RestoreDatabaseRequest struct {
	// Backup: Name of the backup from which to restore. Values are of the form
	// `projects//instances//backups/`.
	Backup string `json:"backup,omitempty"`
	// DatabaseId: Required. The id of the database to create and restore to. This
	// database must not already exist. The `database_id` appended to `parent`
	// forms the full database name of the form `projects//instances//databases/`.
	DatabaseId string `json:"databaseId,omitempty"`
	// EncryptionConfig: Optional. An encryption configuration describing the
	// encryption type and key resources in Cloud KMS used to encrypt/decrypt the
	// database to restore to. If this field is not specified, the restored
	// database will use the same encryption configuration as the backup by
	// default, namely encryption_type = `USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION`.
	EncryptionConfig *RestoreDatabaseEncryptionConfig `json:"encryptionConfig,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Backup") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Backup") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s RestoreDatabaseRequest) MarshalJSON() ([]byte, error) {
	type NoMethod RestoreDatabaseRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RestoreInfo: Information about the database restore.
type RestoreInfo struct {
	// BackupInfo: Information about the backup used to restore the database. The
	// backup may no longer exist.
	BackupInfo *BackupInfo `json:"backupInfo,omitempty"`
	// SourceType: The type of the restore source.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - No restore associated.
	//   "BACKUP" - A backup was used as the source of the restore.
	SourceType string `json:"sourceType,omitempty"`
	// ForceSendFields is a list of field names (e.g. "BackupInfo") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "BackupInfo") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s RestoreInfo) MarshalJSON() ([]byte, error) {
	type NoMethod RestoreInfo
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ResultSet: Results from Read or ExecuteSql.
type ResultSet struct {
	// Metadata: Metadata about the result set, such as row type information.
	Metadata *ResultSetMetadata `json:"metadata,omitempty"`
	// PrecommitToken: Optional. A precommit token is included if the read-write
	// transaction is on a multiplexed session. Pass the precommit token with the
	// highest sequence number from this transaction attempt to the Commit request
	// for this transaction.
	PrecommitToken *MultiplexedSessionPrecommitToken `json:"precommitToken,omitempty"`
	// Rows: Each element in `rows` is a row whose format is defined by
	// metadata.row_type. The ith element in each row matches the ith field in
	// metadata.row_type. Elements are encoded based on type as described here.
	Rows [][]interface{} `json:"rows,omitempty"`
	// Stats: Query plan and execution statistics for the SQL statement that
	// produced this result set. These can be requested by setting
	// ExecuteSqlRequest.query_mode. DML statements always produce stats containing
	// the number of rows modified, unless executed using the
	// ExecuteSqlRequest.QueryMode.PLAN ExecuteSqlRequest.query_mode. Other fields
	// might or might not be populated, based on the ExecuteSqlRequest.query_mode.
	Stats *ResultSetStats `json:"stats,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Metadata") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Metadata") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ResultSet) MarshalJSON() ([]byte, error) {
	type NoMethod ResultSet
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ResultSetMetadata: Metadata about a ResultSet or PartialResultSet.
type ResultSetMetadata struct {
	// RowType: Indicates the field names and types for the rows in the result set.
	// For example, a SQL query like "SELECT UserId, UserName FROM Users" could
	// return a `row_type` value like: "fields": [ { "name": "UserId", "type": {
	// "code": "INT64" } }, { "name": "UserName", "type": { "code": "STRING" } }, ]
	RowType *StructType `json:"rowType,omitempty"`
	// Transaction: If the read or SQL query began a transaction as a side-effect,
	// the information about the new transaction is yielded here.
	Transaction *Transaction `json:"transaction,omitempty"`
	// UndeclaredParameters: A SQL query can be parameterized. In PLAN mode, these
	// parameters can be undeclared. This indicates the field names and types for
	// those undeclared parameters in the SQL query. For example, a SQL query like
	// "SELECT * FROM Users where UserId = @userId and UserName = @userName "
	// could return a `undeclared_parameters` value like: "fields": [ { "name":
	// "UserId", "type": { "code": "INT64" } }, { "name": "UserName", "type": {
	// "code": "STRING" } }, ]
	UndeclaredParameters *StructType `json:"undeclaredParameters,omitempty"`
	// ForceSendFields is a list of field names (e.g. "RowType") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "RowType") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ResultSetMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod ResultSetMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ResultSetStats: Additional statistics about a ResultSet or PartialResultSet.
type ResultSetStats struct {
	// QueryPlan: QueryPlan for the query associated with this result.
	QueryPlan *QueryPlan `json:"queryPlan,omitempty"`
	// QueryStats: Aggregated statistics from the execution of the query. Only
	// present when the query is profiled. For example, a query could return the
	// statistics as follows: { "rows_returned": "3", "elapsed_time": "1.22 secs",
	// "cpu_time": "1.19 secs" }
	QueryStats googleapi.RawMessage `json:"queryStats,omitempty"`
	// RowCountExact: Standard DML returns an exact count of rows that were
	// modified.
	RowCountExact int64 `json:"rowCountExact,omitempty,string"`
	// RowCountLowerBound: Partitioned DML doesn't offer exactly-once semantics, so
	// it returns a lower bound of the rows modified.
	RowCountLowerBound int64 `json:"rowCountLowerBound,omitempty,string"`
	// ForceSendFields is a list of field names (e.g. "QueryPlan") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "QueryPlan") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ResultSetStats) MarshalJSON() ([]byte, error) {
	type NoMethod ResultSetStats
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// RollbackRequest: The request for Rollback.
type RollbackRequest struct {
	// TransactionId: Required. The transaction to roll back.
	TransactionId string `json:"transactionId,omitempty"`
	// ForceSendFields is a list of field names (e.g. "TransactionId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "TransactionId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s RollbackRequest) MarshalJSON() ([]byte, error) {
	type NoMethod RollbackRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Scan: Scan is a structure which describes Cloud Key Visualizer scan
// information.
type Scan struct {
	// Details: Additional information provided by the implementer.
	Details googleapi.RawMessage `json:"details,omitempty"`
	// EndTime: The upper bound for when the scan is defined.
	EndTime string `json:"endTime,omitempty"`
	// Name: The unique name of the scan, specific to the Database service
	// implementing this interface.
	Name string `json:"name,omitempty"`
	// ScanData: Output only. Cloud Key Visualizer scan data. Note, this field is
	// not available to the ListScans method.
	ScanData *ScanData `json:"scanData,omitempty"`
	// StartTime: A range of time (inclusive) for when the scan is defined. The
	// lower bound for when the scan is defined.
	StartTime string `json:"startTime,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Details") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Details") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Scan) MarshalJSON() ([]byte, error) {
	type NoMethod Scan
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ScanData: ScanData contains Cloud Key Visualizer scan data used by the
// caller to construct a visualization.
type ScanData struct {
	// Data: Cloud Key Visualizer scan data. The range of time this information
	// covers is captured via the above time range fields. Note, this field is not
	// available to the ListScans method.
	Data *VisualizationData `json:"data,omitempty"`
	// EndTime: The upper bound for when the contained data is defined.
	EndTime string `json:"endTime,omitempty"`
	// StartTime: A range of time (inclusive) for when the contained data is
	// defined. The lower bound for when the contained data is defined.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Data") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Data") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ScanData) MarshalJSON() ([]byte, error) {
	type NoMethod ScanData
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Send: Arguments to send operations.
type Send struct {
	// DeliverTime: The time at which Spanner will begin attempting to deliver the
	// message. If `deliver_time` is not set, Spanner will deliver the message
	// immediately. If `deliver_time` is in the past, Spanner will replace it with
	// a value closer to the current time.
	DeliverTime string `json:"deliverTime,omitempty"`
	// Key: Required. The primary key of the message to be sent.
	Key []interface{} `json:"key,omitempty"`
	// Payload: The payload of the message.
	Payload interface{} `json:"payload,omitempty"`
	// Queue: Required. The queue to which the message will be sent.
	Queue string `json:"queue,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DeliverTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DeliverTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Send) MarshalJSON() ([]byte, error) {
	type NoMethod Send
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Session: A session in the Cloud Spanner API.
type Session struct {
	// ApproximateLastUseTime: Output only. The approximate timestamp when the
	// session is last used. It's typically earlier than the actual last use time.
	ApproximateLastUseTime string `json:"approximateLastUseTime,omitempty"`
	// CreateTime: Output only. The timestamp when the session is created.
	CreateTime string `json:"createTime,omitempty"`
	// CreatorRole: The database role which created this session.
	CreatorRole string `json:"creatorRole,omitempty"`
	// Labels: The labels for the session. * Label keys must be between 1 and 63
	// characters long and must conform to the following regular expression: `a-z
	// ([-a-z0-9]*[a-z0-9])?`. * Label values must be between 0 and 63 characters
	// long and must conform to the regular expression
	// `([a-z]([-a-z0-9]*[a-z0-9])?)?`. * No more than 64 labels can be associated
	// with a given session. See https://goo.gl/xmQnxf for more information on and
	// examples of labels.
	Labels map[string]string `json:"labels,omitempty"`
	// Multiplexed: Optional. If `true`, specifies a multiplexed session. Use a
	// multiplexed session for multiple, concurrent operations including any
	// combination of read-only and read-write transactions. Use `sessions.create`
	// to create multiplexed sessions. Don't use BatchCreateSessions to create a
	// multiplexed session. You can't delete or list multiplexed sessions.
	Multiplexed bool `json:"multiplexed,omitempty"`
	// Name: Output only. The name of the session. This is always system-assigned.
	Name string `json:"name,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "ApproximateLastUseTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ApproximateLastUseTime") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Session) MarshalJSON() ([]byte, error) {
	type NoMethod Session
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// SetIamPolicyRequest: Request message for `SetIamPolicy` method.
type SetIamPolicyRequest struct {
	// Policy: REQUIRED: The complete policy to be applied to the `resource`. The
	// size of the policy is limited to a few 10s of KB. An empty policy is a valid
	// policy but certain Google Cloud services (such as Projects) might reject
	// them.
	Policy *Policy `json:"policy,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Policy") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Policy") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s SetIamPolicyRequest) MarshalJSON() ([]byte, error) {
	type NoMethod SetIamPolicyRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// ShortRepresentation: Condensed representation of a node and its subtree.
// Only present for `SCALAR` PlanNode(s).
type ShortRepresentation struct {
	// Description: A string representation of the expression subtree rooted at
	// this node.
	Description string `json:"description,omitempty"`
	// Subqueries: A mapping of (subquery variable name) -> (subquery node id) for
	// cases where the `description` string of this node references a `SCALAR`
	// subquery contained in the expression subtree rooted at this node. The
	// referenced `SCALAR` subquery may not necessarily be a direct child of this
	// node.
	Subqueries map[string]int64 `json:"subqueries,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Description") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Description") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s ShortRepresentation) MarshalJSON() ([]byte, error) {
	type NoMethod ShortRepresentation
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// SingleRegionQuorum: Message type for a single-region quorum.
type SingleRegionQuorum struct {
	// ServingLocation: Required. The location of the serving region, for example,
	// "us-central1". The location must be one of the regions within the
	// dual-region instance configuration of your database. The list of valid
	// locations is available using the GetInstanceConfig API. This should only be
	// used if you plan to change quorum to the single-region quorum type.
	ServingLocation string `json:"servingLocation,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ServingLocation") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ServingLocation") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s SingleRegionQuorum) MarshalJSON() ([]byte, error) {
	type NoMethod SingleRegionQuorum
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// SplitPoints: The split points of a table or an index.
type SplitPoints struct {
	// ExpireTime: Optional. The expiration timestamp of the split points. A
	// timestamp in the past means immediate expiration. The maximum value can be
	// 30 days in the future. Defaults to 10 days in the future if not specified.
	ExpireTime string `json:"expireTime,omitempty"`
	// Index: The index to split. If specified, the `table` field must refer to the
	// index's base table.
	Index string `json:"index,omitempty"`
	// Keys: Required. The list of split keys. In essence, the split boundaries.
	Keys []*Key `json:"keys,omitempty"`
	// Table: The table to split.
	Table string `json:"table,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ExpireTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExpireTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s SplitPoints) MarshalJSON() ([]byte, error) {
	type NoMethod SplitPoints
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Statement: A single DML statement.
type Statement struct {
	// ParamTypes: It isn't always possible for Cloud Spanner to infer the right
	// SQL type from a JSON value. For example, values of type `BYTES` and values
	// of type `STRING` both appear in params as JSON strings. In these cases,
	// `param_types` can be used to specify the exact SQL type for some or all of
	// the SQL statement parameters. See the definition of Type for more
	// information about SQL types.
	ParamTypes map[string]Type `json:"paramTypes,omitempty"`
	// Params: Parameter names and values that bind to placeholders in the DML
	// string. A parameter placeholder consists of the `@` character followed by
	// the parameter name (for example, `@firstName`). Parameter names can contain
	// letters, numbers, and underscores. Parameters can appear anywhere that a
	// literal value is expected. The same parameter name can be used more than
	// once, for example: "WHERE id > @msg_id AND id < @msg_id + 100" It's an
	// error to execute a SQL statement with unbound parameters.
	Params googleapi.RawMessage `json:"params,omitempty"`
	// Sql: Required. The DML string.
	Sql string `json:"sql,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ParamTypes") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ParamTypes") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Statement) MarshalJSON() ([]byte, error) {
	type NoMethod Statement
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Status: The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs. It is
// used by gRPC (https://github.com/grpc). Each `Status` message contains three
// pieces of data: error code, error message, and error details. You can find
// out more about this error model and how to work with it in the API Design
// Guide (https://cloud.google.com/apis/design/errors).
type Status struct {
	// Code: The status code, which should be an enum value of google.rpc.Code.
	Code int64 `json:"code,omitempty"`
	// Details: A list of messages that carry the error details. There is a common
	// set of message types for APIs to use.
	Details []googleapi.RawMessage `json:"details,omitempty"`
	// Message: A developer-facing error message, which should be in English. Any
	// user-facing error message should be localized and sent in the
	// google.rpc.Status.details field, or localized by the client.
	Message string `json:"message,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Code") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Code") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Status) MarshalJSON() ([]byte, error) {
	type NoMethod Status
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// StructType: `StructType` defines the fields of a STRUCT type.
type StructType struct {
	// Fields: The list of fields that make up this struct. Order is significant,
	// because values of this struct type are represented as lists, where the order
	// of field values matches the order of fields in the StructType. In turn, the
	// order of fields matches the order of columns in a read request, or the order
	// of fields in the `SELECT` clause of a query.
	Fields []*Field `json:"fields,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Fields") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Fields") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s StructType) MarshalJSON() ([]byte, error) {
	type NoMethod StructType
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TestIamPermissionsRequest: Request message for `TestIamPermissions` method.
type TestIamPermissionsRequest struct {
	// Permissions: REQUIRED: The set of permissions to check for 'resource'.
	// Permissions with wildcards (such as '*', 'spanner.*', 'spanner.instances.*')
	// are not allowed.
	Permissions []string `json:"permissions,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Permissions") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Permissions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s TestIamPermissionsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod TestIamPermissionsRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TestIamPermissionsResponse: Response message for `TestIamPermissions`
// method.
type TestIamPermissionsResponse struct {
	// Permissions: A subset of `TestPermissionsRequest.permissions` that the
	// caller is allowed.
	Permissions []string `json:"permissions,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Permissions") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Permissions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s TestIamPermissionsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod TestIamPermissionsResponse
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Transaction: A transaction.
type Transaction struct {
	// Id: `id` may be used to identify the transaction in subsequent Read,
	// ExecuteSql, Commit, or Rollback calls. Single-use read-only transactions do
	// not have IDs, because single-use transactions do not support multiple
	// requests.
	Id string `json:"id,omitempty"`
	// PrecommitToken: A precommit token is included in the response of a
	// BeginTransaction request if the read-write transaction is on a multiplexed
	// session and a mutation_key was specified in the BeginTransaction. The
	// precommit token with the highest sequence number from this transaction
	// attempt should be passed to the Commit request for this transaction.
	PrecommitToken *MultiplexedSessionPrecommitToken `json:"precommitToken,omitempty"`
	// ReadTimestamp: For snapshot read-only transactions, the read timestamp
	// chosen for the transaction. Not returned by default: see
	// TransactionOptions.ReadOnly.return_read_timestamp. A timestamp in RFC3339
	// UTC \"Zulu\" format, accurate to nanoseconds. Example:
	// "2014-10-02T15:01:23.045123456Z".
	ReadTimestamp string `json:"readTimestamp,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the server.
	googleapi.ServerResponse `json:"-"`
	// ForceSendFields is a list of field names (e.g. "Id") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Id") to include in API requests
	// with the JSON null value. By default, fields with empty values are omitted
	// from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Transaction) MarshalJSON() ([]byte, error) {
	type NoMethod Transaction
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TransactionOptions: Options to use for transactions.
type TransactionOptions struct {
	// ExcludeTxnFromChangeStreams: When `exclude_txn_from_change_streams` is set
	// to `true`, it prevents read or write transactions from being tracked in
	// change streams. * If the DDL option `allow_txn_exclusion` is set to `true`,
	// then the updates made within this transaction aren't recorded in the change
	// stream. * If you don't set the DDL option `allow_txn_exclusion` or if it's
	// set to `false`, then the updates made within this transaction are recorded
	// in the change stream. When `exclude_txn_from_change_streams` is set to
	// `false` or not set, modifications from this transaction are recorded in all
	// change streams that are tracking columns modified by these transactions. The
	// `exclude_txn_from_change_streams` option can only be specified for
	// read-write or partitioned DML transactions, otherwise the API returns an
	// `INVALID_ARGUMENT` error.
	ExcludeTxnFromChangeStreams bool `json:"excludeTxnFromChangeStreams,omitempty"`
	// IsolationLevel: Isolation level for the transaction.
	//
	// Possible values:
	//   "ISOLATION_LEVEL_UNSPECIFIED" - Default value. If the value is not
	// specified, the `SERIALIZABLE` isolation level is used.
	//   "SERIALIZABLE" - All transactions appear as if they executed in a serial
	// order, even if some of the reads, writes, and other operations of distinct
	// transactions actually occurred in parallel. Spanner assigns commit
	// timestamps that reflect the order of committed transactions to implement
	// this property. Spanner offers a stronger guarantee than serializability
	// called external consistency. For more information, see [TrueTime and
	// external
	// consistency](https://cloud.google.com/spanner/docs/true-time-external-consist
	// ency#serializability).
	//   "REPEATABLE_READ" - All reads performed during the transaction observe a
	// consistent snapshot of the database, and the transaction is only
	// successfully committed in the absence of conflicts between its updates and
	// any concurrent updates that have occurred since that snapshot. Consequently,
	// in contrast to `SERIALIZABLE` transactions, only write-write conflicts are
	// detected in snapshot transactions. This isolation level does not support
	// read-only and partitioned DML transactions. When `REPEATABLE_READ` is
	// specified on a read-write transaction, the locking semantics default to
	// `OPTIMISTIC`.
	IsolationLevel string `json:"isolationLevel,omitempty"`
	// PartitionedDml: Partitioned DML transaction. Authorization to begin a
	// Partitioned DML transaction requires
	// `spanner.databases.beginPartitionedDmlTransaction` permission on the
	// `session` resource.
	PartitionedDml *PartitionedDml `json:"partitionedDml,omitempty"`
	// ReadOnly: Transaction does not write. Authorization to begin a read-only
	// transaction requires `spanner.databases.beginReadOnlyTransaction` permission
	// on the `session` resource.
	ReadOnly *ReadOnly `json:"readOnly,omitempty"`
	// ReadWrite: Transaction may write. Authorization to begin a read-write
	// transaction requires `spanner.databases.beginOrRollbackReadWriteTransaction`
	// permission on the `session` resource.
	ReadWrite *ReadWrite `json:"readWrite,omitempty"`
	// ForceSendFields is a list of field names (e.g.
	// "ExcludeTxnFromChangeStreams") to unconditionally include in API requests.
	// By default, fields with empty or default values are omitted from API
	// requests. See https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields
	// for more details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ExcludeTxnFromChangeStreams") to
	// include in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s TransactionOptions) MarshalJSON() ([]byte, error) {
	type NoMethod TransactionOptions
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// TransactionSelector: This message is used to select the transaction in which
// a Read or ExecuteSql call runs. See TransactionOptions for more information
// about transactions.
type TransactionSelector struct {
	// Begin: Begin a new transaction and execute this read or SQL query in it. The
	// transaction ID of the new transaction is returned in
	// ResultSetMetadata.transaction, which is a Transaction.
	Begin *TransactionOptions `json:"begin,omitempty"`
	// Id: Execute the read or SQL query in a previously-started transaction.
	Id string `json:"id,omitempty"`
	// SingleUse: Execute the read or SQL query in a temporary transaction. This is
	// the most efficient way to execute a transaction that consists of a single
	// SQL query.
	SingleUse *TransactionOptions `json:"singleUse,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Begin") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Begin") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s TransactionSelector) MarshalJSON() ([]byte, error) {
	type NoMethod TransactionSelector
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Type: `Type` indicates the type of a Cloud Spanner value, as might be stored
// in a table cell or returned from an SQL query.
type Type struct {
	// ArrayElementType: If code == ARRAY, then `array_element_type` is the type of
	// the array elements.
	ArrayElementType *Type `json:"arrayElementType,omitempty"`
	// Code: Required. The TypeCode for this type.
	//
	// Possible values:
	//   "TYPE_CODE_UNSPECIFIED" - Not specified.
	//   "BOOL" - Encoded as JSON `true` or `false`.
	//   "INT64" - Encoded as `string`, in decimal format.
	//   "FLOAT64" - Encoded as `number`, or the strings "NaN", "Infinity", or
	// "-Infinity".
	//   "FLOAT32" - Encoded as `number`, or the strings "NaN", "Infinity", or
	// "-Infinity".
	//   "TIMESTAMP" - Encoded as `string` in RFC 3339 timestamp format. The time
	// zone must be present, and must be "Z". If the schema has the column option
	// `allow_commit_timestamp=true`, the placeholder string
	// "spanner.commit_timestamp()" can be used to instruct the system to insert
	// the commit timestamp associated with the transaction commit.
	//   "DATE" - Encoded as `string` in RFC 3339 date format.
	//   "STRING" - Encoded as `string`.
	//   "BYTES" - Encoded as a base64-encoded `string`, as described in RFC 4648,
	// section 4.
	//   "ARRAY" - Encoded as `list`, where the list elements are represented
	// according to array_element_type.
	//   "STRUCT" - Encoded as `list`, where list element `i` is represented
	// according to [struct_type.fields[i]][google.spanner.v1.StructType.fields].
	//   "NUMERIC" - Encoded as `string`, in decimal format or scientific notation
	// format. Decimal format: `[+-]Digits[.[Digits]]` or `+-.Digits` Scientific
	// notation: `[+-]Digits[.[Digits]][ExponentIndicator[+-]Digits]` or
	// `+-.Digits[ExponentIndicator[+-]Digits]` (ExponentIndicator is "e" or
	// "E")
	//   "JSON" - Encoded as a JSON-formatted `string` as described in RFC 7159.
	// The following rules are applied when parsing JSON input: - Whitespace
	// characters are not preserved. - If a JSON object has duplicate keys, only
	// the first key is preserved. - Members of a JSON object are not guaranteed to
	// have their order preserved. - JSON array elements will have their order
	// preserved.
	//   "PROTO" - Encoded as a base64-encoded `string`, as described in RFC 4648,
	// section 4.
	//   "ENUM" - Encoded as `string`, in decimal format.
	//   "INTERVAL" - Encoded as `string`, in `ISO8601` duration format -
	// `P[n]Y[n]M[n]DT[n]H[n]M[n[.fraction]]S` where `n` is an integer. For
	// example, `P1Y2M3DT4H5M6.5S` represents time duration of 1 year, 2 months, 3
	// days, 4 hours, 5 minutes, and 6.5 seconds.
	//   "UUID" - Encoded as `string`, in lower-case hexa-decimal format, as
	// described in RFC 9562, section 4.
	Code string `json:"code,omitempty"`
	// ProtoTypeFqn: If code == PROTO or code == ENUM, then `proto_type_fqn` is the
	// fully qualified name of the proto type representing the proto/enum
	// definition.
	ProtoTypeFqn string `json:"protoTypeFqn,omitempty"`
	// StructType: If code == STRUCT, then `struct_type` provides type information
	// for the struct's fields.
	StructType *StructType `json:"structType,omitempty"`
	// TypeAnnotation: The TypeAnnotationCode that disambiguates SQL type that
	// Spanner will use to represent values of this type during query processing.
	// This is necessary for some type codes because a single TypeCode can be
	// mapped to different SQL types depending on the SQL dialect. type_annotation
	// typically is not needed to process the content of a value (it doesn't affect
	// serialization) and clients can ignore it on the read path.
	//
	// Possible values:
	//   "TYPE_ANNOTATION_CODE_UNSPECIFIED" - Not specified.
	//   "PG_NUMERIC" - PostgreSQL compatible NUMERIC type. This annotation needs
	// to be applied to Type instances having NUMERIC type code to specify that
	// values of this type should be treated as PostgreSQL NUMERIC values.
	// Currently this annotation is always needed for NUMERIC when a client
	// interacts with PostgreSQL-enabled Spanner databases.
	//   "PG_JSONB" - PostgreSQL compatible JSONB type. This annotation needs to be
	// applied to Type instances having JSON type code to specify that values of
	// this type should be treated as PostgreSQL JSONB values. Currently this
	// annotation is always needed for JSON when a client interacts with
	// PostgreSQL-enabled Spanner databases.
	//   "PG_OID" - PostgreSQL compatible OID type. This annotation can be used by
	// a client interacting with PostgreSQL-enabled Spanner database to specify
	// that a value should be treated using the semantics of the OID type.
	TypeAnnotation string `json:"typeAnnotation,omitempty"`
	// ForceSendFields is a list of field names (e.g. "ArrayElementType") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "ArrayElementType") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Type) MarshalJSON() ([]byte, error) {
	type NoMethod Type
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateDatabaseDdlMetadata: Metadata type for the operation returned by
// UpdateDatabaseDdl.
type UpdateDatabaseDdlMetadata struct {
	// Actions: The brief action info for the DDL statements. `actions[i]` is the
	// brief info for `statements[i]`.
	Actions []*DdlStatementActionInfo `json:"actions,omitempty"`
	// CommitTimestamps: Reports the commit timestamps of all statements that have
	// succeeded so far, where `commit_timestamps[i]` is the commit timestamp for
	// the statement `statements[i]`.
	CommitTimestamps []string `json:"commitTimestamps,omitempty"`
	// Database: The database being modified.
	Database string `json:"database,omitempty"`
	// Progress: The progress of the UpdateDatabaseDdl operations. All DDL
	// statements will have continuously updating progress, and `progress[i]` is
	// the operation progress for `statements[i]`. Also, `progress[i]` will have
	// start time and end time populated with commit timestamp of operation, as
	// well as a progress of 100% once the operation has completed.
	Progress []*OperationProgress `json:"progress,omitempty"`
	// Statements: For an update this list contains all the statements. For an
	// individual statement, this list contains only that statement.
	Statements []string `json:"statements,omitempty"`
	// Throttled: Output only. When true, indicates that the operation is
	// throttled, for example, due to resource constraints. When resources become
	// available the operation will resume and this field will be false again.
	Throttled bool `json:"throttled,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Actions") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Actions") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateDatabaseDdlMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateDatabaseDdlMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateDatabaseDdlRequest: Enqueues the given DDL statements to be applied,
// in order but not necessarily all at once, to the database schema at some
// point (or points) in the future. The server checks that the statements are
// executable (syntactically valid, name tables that exist, etc.) before
// enqueueing them, but they may still fail upon later execution (for example,
// if a statement from another batch of statements is applied first and it
// conflicts in some way, or if there is some data-related problem like a
// `NULL` value in a column to which `NOT NULL` would be added). If a statement
// fails, all subsequent statements in the batch are automatically cancelled.
// Each batch of statements is assigned a name which can be used with the
// Operations API to monitor progress. See the operation_id field for more
// details.
type UpdateDatabaseDdlRequest struct {
	// OperationId: If empty, the new update request is assigned an
	// automatically-generated operation ID. Otherwise, `operation_id` is used to
	// construct the name of the resulting Operation. Specifying an explicit
	// operation ID simplifies determining whether the statements were executed in
	// the event that the UpdateDatabaseDdl call is replayed, or the return value
	// is otherwise lost: the database and `operation_id` fields can be combined to
	// form the `name` of the resulting longrunning.Operation: `/operations/`.
	// `operation_id` should be unique within the database, and must be a valid
	// identifier: `a-z*`. Note that automatically-generated operation IDs always
	// begin with an underscore. If the named operation already exists,
	// UpdateDatabaseDdl returns `ALREADY_EXISTS`.
	OperationId string `json:"operationId,omitempty"`
	// ProtoDescriptors: Optional. Proto descriptors used by CREATE/ALTER PROTO
	// BUNDLE statements. Contains a protobuf-serialized
	// google.protobuf.FileDescriptorSet
	// (https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
	// To generate it, install (https://grpc.io/docs/protoc-installation/) and run
	// `protoc` with --include_imports and --descriptor_set_out. For example, to
	// generate for moon/shot/app.proto, run ``` $protoc --proto_path=/app_path
	// --proto_path=/lib_path \ --include_imports \
	// --descriptor_set_out=descriptors.data \ moon/shot/app.proto ``` For more
	// details, see protobuffer self description
	// (https://developers.google.com/protocol-buffers/docs/techniques#self-description).
	ProtoDescriptors string `json:"protoDescriptors,omitempty"`
	// Statements: Required. DDL statements to be applied to the database.
	Statements []string `json:"statements,omitempty"`
	// ForceSendFields is a list of field names (e.g. "OperationId") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "OperationId") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateDatabaseDdlRequest) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateDatabaseDdlRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateDatabaseMetadata: Metadata type for the operation returned by
// UpdateDatabase.
type UpdateDatabaseMetadata struct {
	// CancelTime: The time at which this operation was cancelled. If set, this
	// operation is in the process of undoing itself (which is best-effort).
	CancelTime string `json:"cancelTime,omitempty"`
	// Progress: The progress of the UpdateDatabase operation.
	Progress *OperationProgress `json:"progress,omitempty"`
	// Request: The request for UpdateDatabase.
	Request *UpdateDatabaseRequest `json:"request,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateDatabaseMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateDatabaseMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateDatabaseRequest: The request for UpdateDatabase.
type UpdateDatabaseRequest struct {
	// Database: Required. The database to update. The `name` field of the database
	// is of the form `projects//instances//databases/`.
	Database *Database `json:"database,omitempty"`
	// UpdateMask: Required. The list of fields to update. Currently, only
	// `enable_drop_protection` field can be updated.
	UpdateMask string `json:"updateMask,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Database") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Database") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateDatabaseRequest) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateDatabaseRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateInstanceConfigMetadata: Metadata type for the operation returned by
// UpdateInstanceConfig.
type UpdateInstanceConfigMetadata struct {
	// CancelTime: The time at which this operation was cancelled.
	CancelTime string `json:"cancelTime,omitempty"`
	// InstanceConfig: The desired instance configuration after updating.
	InstanceConfig *InstanceConfig `json:"instanceConfig,omitempty"`
	// Progress: The progress of the UpdateInstanceConfig operation.
	Progress *InstanceOperationProgress `json:"progress,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateInstanceConfigMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateInstanceConfigMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateInstanceConfigRequest: The request for UpdateInstanceConfig.
type UpdateInstanceConfigRequest struct {
	// InstanceConfig: Required. The user instance configuration to update, which
	// must always include the instance configuration name. Otherwise, only fields
	// mentioned in update_mask need be included. To prevent conflicts of
	// concurrent updates, etag can be used.
	InstanceConfig *InstanceConfig `json:"instanceConfig,omitempty"`
	// UpdateMask: Required. A mask specifying which fields in InstanceConfig
	// should be updated. The field mask must always be specified; this prevents
	// any future fields in InstanceConfig from being erased accidentally by
	// clients that do not know about them. Only display_name and labels can be
	// updated.
	UpdateMask string `json:"updateMask,omitempty"`
	// ValidateOnly: An option to validate, but not actually execute, a request,
	// and provide the same response.
	ValidateOnly bool `json:"validateOnly,omitempty"`
	// ForceSendFields is a list of field names (e.g. "InstanceConfig") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "InstanceConfig") to include in
	// API requests with the JSON null value. By default, fields with empty values
	// are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateInstanceConfigRequest) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateInstanceConfigRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateInstanceMetadata: Metadata type for the operation returned by
// UpdateInstance.
type UpdateInstanceMetadata struct {
	// CancelTime: The time at which this operation was cancelled. If set, this
	// operation is in the process of undoing itself (which is guaranteed to
	// succeed) and cannot be cancelled again.
	CancelTime string `json:"cancelTime,omitempty"`
	// EndTime: The time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// ExpectedFulfillmentPeriod: The expected fulfillment period of this update
	// operation.
	//
	// Possible values:
	//   "FULFILLMENT_PERIOD_UNSPECIFIED" - Not specified.
	//   "FULFILLMENT_PERIOD_NORMAL" - Normal fulfillment period. The operation is
	// expected to complete within minutes.
	//   "FULFILLMENT_PERIOD_EXTENDED" - Extended fulfillment period. It can take
	// up to an hour for the operation to complete.
	ExpectedFulfillmentPeriod string `json:"expectedFulfillmentPeriod,omitempty"`
	// Instance: The desired end state of the update.
	Instance *Instance `json:"instance,omitempty"`
	// StartTime: The time at which UpdateInstance request was received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateInstanceMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateInstanceMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateInstancePartitionMetadata: Metadata type for the operation returned by
// UpdateInstancePartition.
type UpdateInstancePartitionMetadata struct {
	// CancelTime: The time at which this operation was cancelled. If set, this
	// operation is in the process of undoing itself (which is guaranteed to
	// succeed) and cannot be cancelled again.
	CancelTime string `json:"cancelTime,omitempty"`
	// EndTime: The time at which this operation failed or was completed
	// successfully.
	EndTime string `json:"endTime,omitempty"`
	// InstancePartition: The desired end state of the update.
	InstancePartition *InstancePartition `json:"instancePartition,omitempty"`
	// StartTime: The time at which UpdateInstancePartition request was received.
	StartTime string `json:"startTime,omitempty"`
	// ForceSendFields is a list of field names (e.g. "CancelTime") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "CancelTime") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateInstancePartitionMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateInstancePartitionMetadata
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateInstancePartitionRequest: The request for UpdateInstancePartition.
type UpdateInstancePartitionRequest struct {
	// FieldMask: Required. A mask specifying which fields in InstancePartition
	// should be updated. The field mask must always be specified; this prevents
	// any future fields in InstancePartition from being erased accidentally by
	// clients that do not know about them.
	FieldMask string `json:"fieldMask,omitempty"`
	// InstancePartition: Required. The instance partition to update, which must
	// always include the instance partition name. Otherwise, only fields mentioned
	// in field_mask need be included.
	InstancePartition *InstancePartition `json:"instancePartition,omitempty"`
	// ForceSendFields is a list of field names (e.g. "FieldMask") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "FieldMask") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateInstancePartitionRequest) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateInstancePartitionRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// UpdateInstanceRequest: The request for UpdateInstance.
type UpdateInstanceRequest struct {
	// FieldMask: Required. A mask specifying which fields in Instance should be
	// updated. The field mask must always be specified; this prevents any future
	// fields in Instance from being erased accidentally by clients that do not
	// know about them.
	FieldMask string `json:"fieldMask,omitempty"`
	// Instance: Required. The instance to update, which must always include the
	// instance name. Otherwise, only fields mentioned in field_mask need be
	// included.
	Instance *Instance `json:"instance,omitempty"`
	// ForceSendFields is a list of field names (e.g. "FieldMask") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "FieldMask") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s UpdateInstanceRequest) MarshalJSON() ([]byte, error) {
	type NoMethod UpdateInstanceRequest
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

type VisualizationData struct {
	// DataSourceEndToken: The token signifying the end of a data_source.
	DataSourceEndToken string `json:"dataSourceEndToken,omitempty"`
	// DataSourceSeparatorToken: The token delimiting a datasource name from the
	// rest of a key in a data_source.
	DataSourceSeparatorToken string `json:"dataSourceSeparatorToken,omitempty"`
	// DiagnosticMessages: The list of messages (info, alerts, ...)
	DiagnosticMessages []*DiagnosticMessage `json:"diagnosticMessages,omitempty"`
	// EndKeyStrings: We discretize the entire keyspace into buckets. Assuming each
	// bucket has an inclusive keyrange and covers keys from k(i) ... k(n). In this
	// case k(n) would be an end key for a given range. end_key_string is the
	// collection of all such end keys
	EndKeyStrings []string `json:"endKeyStrings,omitempty"`
	// HasPii: Whether this scan contains PII.
	HasPii bool `json:"hasPii,omitempty"`
	// IndexedKeys: Keys of key ranges that contribute significantly to a given
	// metric Can be thought of as heavy hitters.
	IndexedKeys []string `json:"indexedKeys,omitempty"`
	// KeySeparator: The token delimiting the key prefixes.
	KeySeparator string `json:"keySeparator,omitempty"`
	// KeyUnit: The unit for the key: e.g. 'key' or 'chunk'.
	//
	// Possible values:
	//   "KEY_UNIT_UNSPECIFIED" - Required default value
	//   "KEY" - Each entry corresponds to one key
	//   "CHUNK" - Each entry corresponds to a chunk of keys
	KeyUnit string `json:"keyUnit,omitempty"`
	// Metrics: The list of data objects for each metric.
	Metrics []*Metric `json:"metrics,omitempty"`
	// PrefixNodes: The list of extracted key prefix nodes used in the key prefix
	// hierarchy.
	PrefixNodes []*PrefixNode `json:"prefixNodes,omitempty"`
	// ForceSendFields is a list of field names (e.g. "DataSourceEndToken") to
	// unconditionally include in API requests. By default, fields with empty or
	// default values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "DataSourceEndToken") to include
	// in API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s VisualizationData) MarshalJSON() ([]byte, error) {
	type NoMethod VisualizationData
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

// Write: Arguments to insert, update, insert_or_update, and replace
// operations.
type Write struct {
	// Columns: The names of the columns in table to be written. The list of
	// columns must contain enough columns to allow Cloud Spanner to derive values
	// for all primary key columns in the row(s) to be modified.
	Columns []string `json:"columns,omitempty"`
	// Table: Required. The table whose rows will be written.
	Table string `json:"table,omitempty"`
	// Values: The values to be written. `values` can contain more than one list of
	// values. If it does, then multiple rows are written, one for each entry in
	// `values`. Each list in `values` must have exactly as many entries as there
	// are entries in columns above. Sending multiple lists is equivalent to
	// sending multiple `Mutation`s, each containing one `values` entry and
	// repeating table and columns. Individual values in each list are encoded as
	// described here.
	Values [][]interface{} `json:"values,omitempty"`
	// ForceSendFields is a list of field names (e.g. "Columns") to unconditionally
	// include in API requests. By default, fields with empty or default values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more
	// details.
	ForceSendFields []string `json:"-"`
	// NullFields is a list of field names (e.g. "Columns") to include in API
	// requests with the JSON null value. By default, fields with empty values are
	// omitted from API requests. See
	// https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details.
	NullFields []string `json:"-"`
}

func (s Write) MarshalJSON() ([]byte, error) {
	type NoMethod Write
	return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields)
}

type ProjectsInstanceConfigOperationsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists the user-managed instance configuration long-running operations
// in the given project. An instance configuration operation has a name of the
// form `projects//instanceConfigs//operations/`. The long-running operation
// metadata field type `metadata.type_url` describes the type of the metadata.
// Operations returned include those that have completed/failed/canceled within
// the last 7 days, and pending operations. Operations returned are ordered by
// `operation.metadata.value.start_time` in descending order starting from the
// most recently started operation.
//
//   - parent: The project of the instance configuration operations. Values are
//     of the form `projects/`.
func (r *ProjectsInstanceConfigOperationsService) List(parent string) *ProjectsInstanceConfigOperationsListCall {
	c := &ProjectsInstanceConfigOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": An expression that filters the
// list of returned operations. A filter expression consists of a field name, a
// comparison operator, and a value for filtering. The value must be a string,
// a number, or a boolean. The comparison operator must be one of: `<`, `>`,
// `<=`, `>=`, `!=`, `=`, or `:`. Colon `:` is the contains operator. Filter
// rules are not case sensitive. The following fields in the Operation are
// eligible for filtering: * `name` - The name of the long-running operation *
// `done` - False if the operation is in progress, else true. *
// `metadata.@type` - the type of metadata. For example, the type string for
// CreateInstanceConfigMetadata is
// `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstanceConfigMet
// adata`. * `metadata.` - any field in metadata.value. `metadata.@type` must
// be specified first, if filtering on metadata fields. * `error` - Error
// associated with the long-running operation. * `response.@type` - the type of
// response. * `response.` - any field in response.value. You can combine
// multiple expressions by enclosing each expression in parentheses. By
// default, expressions are combined with AND logic. However, you can specify
// AND, OR, and NOT logic explicitly. Here are a few examples: * `done:true` -
// The operation is complete. * `(metadata.@type=` \
// `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstanceConfigMet
// adata) AND` \ `(metadata.instance_config.name:custom-config) AND` \
// `(metadata.progress.start_time < \"2021-03-28T14:50:00Z\") AND` \
// `(error:*)` - Return operations where: * The operation's metadata type is
// CreateInstanceConfigMetadata. * The instance configuration name contains
// "custom-config". * The operation started before 2021-03-28T14:50:00Z. * The
// operation resulted in an error.
func (c *ProjectsInstanceConfigOperationsListCall) Filter(filter string) *ProjectsInstanceConfigOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of operations to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstanceConfigOperationsListCall) PageSize(pageSize int64) *ProjectsInstanceConfigOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListInstanceConfigOperationsResponse to the same `parent` and with the same
// `filter`.
func (c *ProjectsInstanceConfigOperationsListCall) PageToken(pageToken string) *ProjectsInstanceConfigOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigOperationsListCall) Context(ctx context.Context) *ProjectsInstanceConfigOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instanceConfigOperations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigOperations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigOperations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListInstanceConfigOperationsResponse.ServerResponse.Header or (if a
// response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigOperationsListCall) Do(opts ...googleapi.CallOption) (*ListInstanceConfigOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListInstanceConfigOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigOperations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstanceConfigOperationsListCall) Pages(ctx context.Context, f func(*ListInstanceConfigOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstanceConfigsCreateCall struct {
	s                           *Service
	parent                      string
	createinstanceconfigrequest *CreateInstanceConfigRequest
	urlParams_                  gensupport.URLParams
	ctx_                        context.Context
	header_                     http.Header
}

// Create: Creates an instance configuration and begins preparing it to be
// used. The returned long-running operation can be used to track the progress
// of preparing the new instance configuration. The instance configuration name
// is assigned by the caller. If the named instance configuration already
// exists, `CreateInstanceConfig` returns `ALREADY_EXISTS`. Immediately after
// the request returns: * The instance configuration is readable via the API,
// with all requested attributes. The instance configuration's reconciling
// field is set to true. Its state is `CREATING`. While the operation is
// pending: * Cancelling the operation renders the instance configuration
// immediately unreadable via the API. * Except for deleting the creating
// resource, all other attempts to modify the instance configuration are
// rejected. Upon completion of the returned operation: * Instances can be
// created using the instance configuration. * The instance configuration's
// reconciling field becomes false. Its state becomes `READY`. The returned
// long-running operation will have a name of the format `/operations/` and can
// be used to track creation of the instance configuration. The metadata field
// type is CreateInstanceConfigMetadata. The response field type is
// InstanceConfig, if successful. Authorization requires
// `spanner.instanceConfigs.create` permission on the resource parent.
//
//   - parent: The name of the project in which to create the instance
//     configuration. Values are of the form `projects/`.
func (r *ProjectsInstanceConfigsService) Create(parent string, createinstanceconfigrequest *CreateInstanceConfigRequest) *ProjectsInstanceConfigsCreateCall {
	c := &ProjectsInstanceConfigsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.createinstanceconfigrequest = createinstanceconfigrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsCreateCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsCreateCall) Context(ctx context.Context) *ProjectsInstanceConfigsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.createinstanceconfigrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instanceConfigs")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsCreateCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes the instance configuration. Deletion is only allowed when no
// instances are using the configuration. If any instances are using the
// configuration, returns `FAILED_PRECONDITION`. Only user-managed
// configurations can be deleted. Authorization requires
// `spanner.instanceConfigs.delete` permission on the resource name.
//
//   - name: The name of the instance configuration to be deleted. Values are of
//     the form `projects//instanceConfigs/`.
func (r *ProjectsInstanceConfigsService) Delete(name string) *ProjectsInstanceConfigsDeleteCall {
	c := &ProjectsInstanceConfigsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Etag sets the optional parameter "etag": Used for optimistic concurrency
// control as a way to help prevent simultaneous deletes of an instance
// configuration from overwriting each other. If not empty, the API only
// deletes the instance configuration when the etag provided matches the
// current status of the requested instance configuration. Otherwise, deletes
// the instance configuration without checking the current status of the
// requested instance configuration.
func (c *ProjectsInstanceConfigsDeleteCall) Etag(etag string) *ProjectsInstanceConfigsDeleteCall {
	c.urlParams_.Set("etag", etag)
	return c
}

// ValidateOnly sets the optional parameter "validateOnly": An option to
// validate, but not actually execute, a request, and provide the same
// response.
func (c *ProjectsInstanceConfigsDeleteCall) ValidateOnly(validateOnly bool) *ProjectsInstanceConfigsDeleteCall {
	c.urlParams_.Set("validateOnly", fmt.Sprint(validateOnly))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsDeleteCall) Context(ctx context.Context) *ProjectsInstanceConfigsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets information about a particular instance configuration.
//
//   - name: The name of the requested instance configuration. Values are of the
//     form `projects//instanceConfigs/`.
func (r *ProjectsInstanceConfigsService) Get(name string) *ProjectsInstanceConfigsGetCall {
	c := &ProjectsInstanceConfigsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsGetCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigsGetCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsGetCall) Context(ctx context.Context) *ProjectsInstanceConfigsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *InstanceConfig.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsGetCall) Do(opts ...googleapi.CallOption) (*InstanceConfig, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &InstanceConfig{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists the supported instance configurations for a given project.
// Returns both Google-managed configurations and user-managed configurations.
//
//   - parent: The name of the project for which a list of supported instance
//     configurations is requested. Values are of the form `projects/`.
func (r *ProjectsInstanceConfigsService) List(parent string) *ProjectsInstanceConfigsListCall {
	c := &ProjectsInstanceConfigsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": Number of instance
// configurations to be returned in the response. If 0 or less, defaults to the
// server's maximum allowed page size.
func (c *ProjectsInstanceConfigsListCall) PageSize(pageSize int64) *ProjectsInstanceConfigsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListInstanceConfigsResponse.
func (c *ProjectsInstanceConfigsListCall) PageToken(pageToken string) *ProjectsInstanceConfigsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsListCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigsListCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsListCall) Context(ctx context.Context) *ProjectsInstanceConfigsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instanceConfigs")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListInstanceConfigsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsListCall) Do(opts ...googleapi.CallOption) (*ListInstanceConfigsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListInstanceConfigsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstanceConfigsListCall) Pages(ctx context.Context, f func(*ListInstanceConfigsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstanceConfigsPatchCall struct {
	s                           *Service
	nameid                      string
	updateinstanceconfigrequest *UpdateInstanceConfigRequest
	urlParams_                  gensupport.URLParams
	ctx_                        context.Context
	header_                     http.Header
}

// Patch: Updates an instance configuration. The returned long-running
// operation can be used to track the progress of updating the instance. If the
// named instance configuration does not exist, returns `NOT_FOUND`. Only
// user-managed configurations can be updated. Immediately after the request
// returns: * The instance configuration's reconciling field is set to true.
// While the operation is pending: * Cancelling the operation sets its
// metadata's cancel_time. The operation is guaranteed to succeed at undoing
// all changes, after which point it terminates with a `CANCELLED` status. *
// All other attempts to modify the instance configuration are rejected. *
// Reading the instance configuration via the API continues to give the
// pre-request values. Upon completion of the returned operation: * Creating
// instances using the instance configuration uses the new values. * The new
// values of the instance configuration are readable via the API. * The
// instance configuration's reconciling field becomes false. The returned
// long-running operation will have a name of the format `/operations/` and can
// be used to track the instance configuration modification. The metadata field
// type is UpdateInstanceConfigMetadata. The response field type is
// InstanceConfig, if successful. Authorization requires
// `spanner.instanceConfigs.update` permission on the resource name.
//
//   - name: A unique identifier for the instance configuration. Values are of
//     the form `projects//instanceConfigs/a-z*`. User instance configuration
//     must start with `custom-`.
func (r *ProjectsInstanceConfigsService) Patch(nameid string, updateinstanceconfigrequest *UpdateInstanceConfigRequest) *ProjectsInstanceConfigsPatchCall {
	c := &ProjectsInstanceConfigsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	c.updateinstanceconfigrequest = updateinstanceconfigrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsPatchCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsPatchCall) Context(ctx context.Context) *ProjectsInstanceConfigsPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.updateinstanceconfigrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsOperationsCancelCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Cancel: Starts asynchronous cancellation on a long-running operation. The
// server makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation, the
// operation is not deleted; instead, it becomes an operation with an
// Operation.error value with a google.rpc.Status.code of `1`, corresponding to
// `Code.CANCELLED`.
//
// - name: The name of the operation resource to be cancelled.
func (r *ProjectsInstanceConfigsOperationsService) Cancel(name string) *ProjectsInstanceConfigsOperationsCancelCall {
	c := &ProjectsInstanceConfigsOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsOperationsCancelCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsOperationsCancelCall) Context(ctx context.Context) *ProjectsInstanceConfigsOperationsCancelCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsOperationsCancelCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsOperationsCancelCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.cancel", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.operations.cancel" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsOperationsCancelCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.cancel", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsOperationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a long-running operation. This method indicates that the
// client is no longer interested in the operation result. It does not cancel
// the operation. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`.
//
// - name: The name of the operation resource to be deleted.
func (r *ProjectsInstanceConfigsOperationsService) Delete(name string) *ProjectsInstanceConfigsOperationsDeleteCall {
	c := &ProjectsInstanceConfigsOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsOperationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsOperationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsOperationsDeleteCall) Context(ctx context.Context) *ProjectsInstanceConfigsOperationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsOperationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsOperationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.operations.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsOperationsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
// service.
//
// - name: The name of the operation resource.
func (r *ProjectsInstanceConfigsOperationsService) Get(name string) *ProjectsInstanceConfigsOperationsGetCall {
	c := &ProjectsInstanceConfigsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigsOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsOperationsGetCall) Context(ctx context.Context) *ProjectsInstanceConfigsOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.operations.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the request. If
// the server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// - name: The name of the operation's parent resource.
func (r *ProjectsInstanceConfigsOperationsService) List(name string) *ProjectsInstanceConfigsOperationsListCall {
	c := &ProjectsInstanceConfigsOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list filter.
func (c *ProjectsInstanceConfigsOperationsListCall) Filter(filter string) *ProjectsInstanceConfigsOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list page
// size.
func (c *ProjectsInstanceConfigsOperationsListCall) PageSize(pageSize int64) *ProjectsInstanceConfigsOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list page
// token.
func (c *ProjectsInstanceConfigsOperationsListCall) PageToken(pageToken string) *ProjectsInstanceConfigsOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// ReturnPartialSuccess sets the optional parameter "returnPartialSuccess":
// When set to `true`, operations that are reachable are returned as normal,
// and those that are unreachable are returned in the
// ListOperationsResponse.unreachable field. This can only be `true` when
// reading across collections. For example, when `parent` is set to
// "projects/example/locations/-". This field is not supported by default and
// will result in an `UNIMPLEMENTED` error if set unless explicitly documented
// otherwise in service or product specific documentation.
func (c *ProjectsInstanceConfigsOperationsListCall) ReturnPartialSuccess(returnPartialSuccess bool) *ProjectsInstanceConfigsOperationsListCall {
	c.urlParams_.Set("returnPartialSuccess", fmt.Sprint(returnPartialSuccess))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigsOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigsOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsOperationsListCall) Context(ctx context.Context) *ProjectsInstanceConfigsOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.operations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOperationsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstanceConfigsOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.operations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstanceConfigsOperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstanceConfigsSsdCachesOperationsCancelCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Cancel: Starts asynchronous cancellation on a long-running operation. The
// server makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation, the
// operation is not deleted; instead, it becomes an operation with an
// Operation.error value with a google.rpc.Status.code of `1`, corresponding to
// `Code.CANCELLED`.
//
// - name: The name of the operation resource to be cancelled.
func (r *ProjectsInstanceConfigsSsdCachesOperationsService) Cancel(name string) *ProjectsInstanceConfigsSsdCachesOperationsCancelCall {
	c := &ProjectsInstanceConfigsSsdCachesOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsSsdCachesOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsSsdCachesOperationsCancelCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsSsdCachesOperationsCancelCall) Context(ctx context.Context) *ProjectsInstanceConfigsSsdCachesOperationsCancelCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsSsdCachesOperationsCancelCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsSsdCachesOperationsCancelCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.cancel", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.ssdCaches.operations.cancel" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsSsdCachesOperationsCancelCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.cancel", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsSsdCachesOperationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a long-running operation. This method indicates that the
// client is no longer interested in the operation result. It does not cancel
// the operation. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`.
//
// - name: The name of the operation resource to be deleted.
func (r *ProjectsInstanceConfigsSsdCachesOperationsService) Delete(name string) *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall {
	c := &ProjectsInstanceConfigsSsdCachesOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall) Context(ctx context.Context) *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.ssdCaches.operations.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsSsdCachesOperationsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsSsdCachesOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
// service.
//
// - name: The name of the operation resource.
func (r *ProjectsInstanceConfigsSsdCachesOperationsService) Get(name string) *ProjectsInstanceConfigsSsdCachesOperationsGetCall {
	c := &ProjectsInstanceConfigsSsdCachesOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsSsdCachesOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsSsdCachesOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigsSsdCachesOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigsSsdCachesOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsSsdCachesOperationsGetCall) Context(ctx context.Context) *ProjectsInstanceConfigsSsdCachesOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsSsdCachesOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsSsdCachesOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.ssdCaches.operations.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstanceConfigsSsdCachesOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstanceConfigsSsdCachesOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the request. If
// the server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// - name: The name of the operation's parent resource.
func (r *ProjectsInstanceConfigsSsdCachesOperationsService) List(name string) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c := &ProjectsInstanceConfigsSsdCachesOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list filter.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) Filter(filter string) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list page
// size.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) PageSize(pageSize int64) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list page
// token.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) PageToken(pageToken string) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// ReturnPartialSuccess sets the optional parameter "returnPartialSuccess":
// When set to `true`, operations that are reachable are returned as normal,
// and those that are unreachable are returned in the
// ListOperationsResponse.unreachable field. This can only be `true` when
// reading across collections. For example, when `parent` is set to
// "projects/example/locations/-". This field is not supported by default and
// will result in an `UNIMPLEMENTED` error if set unless explicitly documented
// otherwise in service or product specific documentation.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) ReturnPartialSuccess(returnPartialSuccess bool) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.urlParams_.Set("returnPartialSuccess", fmt.Sprint(returnPartialSuccess))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) Context(ctx context.Context) *ProjectsInstanceConfigsSsdCachesOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instanceConfigs.ssdCaches.operations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOperationsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instanceConfigs.ssdCaches.operations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstanceConfigsSsdCachesOperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesCreateCall struct {
	s                     *Service
	parent                string
	createinstancerequest *CreateInstanceRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// Create: Creates an instance and begins preparing it to begin serving. The
// returned long-running operation can be used to track the progress of
// preparing the new instance. The instance name is assigned by the caller. If
// the named instance already exists, `CreateInstance` returns
// `ALREADY_EXISTS`. Immediately upon completion of this request: * The
// instance is readable via the API, with all requested attributes but no
// allocated resources. Its state is `CREATING`. Until completion of the
// returned operation: * Cancelling the operation renders the instance
// immediately unreadable via the API. * The instance can be deleted. * All
// other attempts to modify the instance are rejected. Upon completion of the
// returned operation: * Billing for all successfully-allocated resources
// begins (some types may have lower than the requested levels). * Databases
// can be created in the instance. * The instance's allocated resource levels
// are readable via the API. * The instance's state becomes `READY`. The
// returned long-running operation will have a name of the format
// `/operations/` and can be used to track creation of the instance. The
// metadata field type is CreateInstanceMetadata. The response field type is
// Instance, if successful.
//
//   - parent: The name of the project in which to create the instance. Values
//     are of the form `projects/`.
func (r *ProjectsInstancesService) Create(parent string, createinstancerequest *CreateInstanceRequest) *ProjectsInstancesCreateCall {
	c := &ProjectsInstancesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.createinstancerequest = createinstancerequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesCreateCall) Context(ctx context.Context) *ProjectsInstancesCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.createinstancerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instances")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesCreateCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes an instance. Immediately upon completion of the request: *
// Billing ceases for all of the instance's reserved resources. Soon afterward:
// * The instance and *all of its databases* immediately and irrevocably
// disappear from the API. All data in the databases is permanently deleted.
//
//   - name: The name of the instance to be deleted. Values are of the form
//     `projects//instances/`.
func (r *ProjectsInstancesService) Delete(name string) *ProjectsInstancesDeleteCall {
	c := &ProjectsInstancesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDeleteCall) Context(ctx context.Context) *ProjectsInstancesDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets information about a particular instance.
//
//   - name: The name of the requested instance. Values are of the form
//     `projects//instances/`.
func (r *ProjectsInstancesService) Get(name string) *ProjectsInstancesGetCall {
	c := &ProjectsInstancesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// FieldMask sets the optional parameter "fieldMask": If field_mask is present,
// specifies the subset of Instance fields that should be returned. If absent,
// all Instance fields are returned.
func (c *ProjectsInstancesGetCall) FieldMask(fieldMask string) *ProjectsInstancesGetCall {
	c.urlParams_.Set("fieldMask", fieldMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesGetCall) Context(ctx context.Context) *ProjectsInstancesGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Instance.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesGetCall) Do(opts ...googleapi.CallOption) (*Instance, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Instance{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesGetIamPolicyCall struct {
	s                   *Service
	resource            string
	getiampolicyrequest *GetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// GetIamPolicy: Gets the access control policy for an instance resource.
// Returns an empty policy if an instance exists but does not have a policy
// set. Authorization requires `spanner.instances.getIamPolicy` on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being retrieved. The format is `projects//instances/` for instance
//     resources and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesService) GetIamPolicy(resource string, getiampolicyrequest *GetIamPolicyRequest) *ProjectsInstancesGetIamPolicyCall {
	c := &ProjectsInstancesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.getiampolicyrequest = getiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesGetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesGetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesGetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesGetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesGetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.getiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.getIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.getIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.getIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists all instances in the given project.
//
//   - parent: The name of the project for which a list of instances is
//     requested. Values are of the form `projects/`.
func (r *ProjectsInstancesService) List(parent string) *ProjectsInstancesListCall {
	c := &ProjectsInstancesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": An expression for filtering the
// results of the request. Filter rules are case insensitive. The fields
// eligible for filtering are: * `name` * `display_name` * `labels.key` where
// key is the name of a label Some examples of using filters are: * `name:*`
// --> The instance has a name. * `name:Howl` --> The instance's name contains
// the string "howl". * `name:HOWL` --> Equivalent to above. * `NAME:howl` -->
// Equivalent to above. * `labels.env:*` --> The instance has the label "env".
// * `labels.env:dev` --> The instance has the label "env" and the value of the
// label contains the string "dev". * `name:howl labels.env:dev` --> The
// instance's name contains "howl" and it has the label "env" with its value
// containing "dev".
func (c *ProjectsInstancesListCall) Filter(filter string) *ProjectsInstancesListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// InstanceDeadline sets the optional parameter "instanceDeadline": Deadline
// used while retrieving metadata for instances. Instances whose metadata
// cannot be retrieved within this deadline will be added to unreachable in
// ListInstancesResponse.
func (c *ProjectsInstancesListCall) InstanceDeadline(instanceDeadline string) *ProjectsInstancesListCall {
	c.urlParams_.Set("instanceDeadline", instanceDeadline)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of instances to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesListCall) PageSize(pageSize int64) *ProjectsInstancesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListInstancesResponse.
func (c *ProjectsInstancesListCall) PageToken(pageToken string) *ProjectsInstancesListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesListCall) Fields(s ...googleapi.Field) *ProjectsInstancesListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesListCall) IfNoneMatch(entityTag string) *ProjectsInstancesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesListCall) Context(ctx context.Context) *ProjectsInstancesListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instances")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListInstancesResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesListCall) Do(opts ...googleapi.CallOption) (*ListInstancesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListInstancesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesListCall) Pages(ctx context.Context, f func(*ListInstancesResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesMoveCall struct {
	s                   *Service
	name                string
	moveinstancerequest *MoveInstanceRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// Move: Moves an instance to the target instance configuration. You can use
// the returned long-running operation to track the progress of moving the
// instance. `MoveInstance` returns `FAILED_PRECONDITION` if the instance meets
// any of the following criteria: * Is undergoing a move to a different
// instance configuration * Has backups * Has an ongoing update * Contains any
// CMEK-enabled databases * Is a free trial instance While the operation is
// pending: * All other attempts to modify the instance, including changes to
// its compute capacity, are rejected. * The following database and backup
// admin operations are rejected: * `DatabaseAdmin.CreateDatabase` *
// `DatabaseAdmin.UpdateDatabaseDdl` (disabled if default_leader is specified
// in the request.) * `DatabaseAdmin.RestoreDatabase` *
// `DatabaseAdmin.CreateBackup` * `DatabaseAdmin.CopyBackup` * Both the source
// and target instance configurations are subject to hourly compute and storage
// charges. * The instance might experience higher read-write latencies and a
// higher transaction abort rate. However, moving an instance doesn't cause any
// downtime. The returned long-running operation has a name of the format
// `/operations/` and can be used to track the move instance operation. The
// metadata field type is MoveInstanceMetadata. The response field type is
// Instance, if successful. Cancelling the operation sets its metadata's
// cancel_time. Cancellation is not immediate because it involves moving any
// data previously moved to the target instance configuration back to the
// original instance configuration. You can use this operation to track the
// progress of the cancellation. Upon successful completion of the
// cancellation, the operation terminates with `CANCELLED` status. If not
// cancelled, upon completion of the returned operation: * The instance
// successfully moves to the target instance configuration. * You are billed
// for compute and storage in target instance configuration. Authorization
// requires the `spanner.instances.update` permission on the resource instance.
// For more details, see Move an instance
// (https://cloud.google.com/spanner/docs/move-instance).
//
// - name: The instance to move. Values are of the form `projects//instances/`.
func (r *ProjectsInstancesService) Move(name string, moveinstancerequest *MoveInstanceRequest) *ProjectsInstancesMoveCall {
	c := &ProjectsInstancesMoveCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.moveinstancerequest = moveinstancerequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesMoveCall) Fields(s ...googleapi.Field) *ProjectsInstancesMoveCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesMoveCall) Context(ctx context.Context) *ProjectsInstancesMoveCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesMoveCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesMoveCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.moveinstancerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:move")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.move", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.move" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesMoveCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.move", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesPatchCall struct {
	s                     *Service
	nameid                string
	updateinstancerequest *UpdateInstanceRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// Patch: Updates an instance, and begins allocating or releasing resources as
// requested. The returned long-running operation can be used to track the
// progress of updating the instance. If the named instance does not exist,
// returns `NOT_FOUND`. Immediately upon completion of this request: * For
// resource types for which a decrease in the instance's allocation has been
// requested, billing is based on the newly-requested level. Until completion
// of the returned operation: * Cancelling the operation sets its metadata's
// cancel_time, and begins restoring resources to their pre-request values. The
// operation is guaranteed to succeed at undoing all resource changes, after
// which point it terminates with a `CANCELLED` status. * All other attempts to
// modify the instance are rejected. * Reading the instance via the API
// continues to give the pre-request resource levels. Upon completion of the
// returned operation: * Billing begins for all successfully-allocated
// resources (some types may have lower than the requested levels). * All
// newly-reserved resources are available for serving the instance's tables. *
// The instance's new resource levels are readable via the API. The returned
// long-running operation will have a name of the format `/operations/` and can
// be used to track the instance modification. The metadata field type is
// UpdateInstanceMetadata. The response field type is Instance, if successful.
// Authorization requires `spanner.instances.update` permission on the resource
// name.
//
//   - name: A unique identifier for the instance, which cannot be changed after
//     the instance is created. Values are of the form
//     `projects//instances/a-z*[a-z0-9]`. The final segment of the name must be
//     between 2 and 64 characters in length.
func (r *ProjectsInstancesService) Patch(nameid string, updateinstancerequest *UpdateInstanceRequest) *ProjectsInstancesPatchCall {
	c := &ProjectsInstancesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	c.updateinstancerequest = updateinstancerequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesPatchCall) Fields(s ...googleapi.Field) *ProjectsInstancesPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesPatchCall) Context(ctx context.Context) *ProjectsInstancesPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.updateinstancerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesSetIamPolicyCall struct {
	s                   *Service
	resource            string
	setiampolicyrequest *SetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// SetIamPolicy: Sets the access control policy on an instance resource.
// Replaces any existing policy. Authorization requires
// `spanner.instances.setIamPolicy` on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being set. The format is `projects//instances/` for instance resources and
//     `projects//instances//databases/` for databases resources.
func (r *ProjectsInstancesService) SetIamPolicy(resource string, setiampolicyrequest *SetIamPolicyRequest) *ProjectsInstancesSetIamPolicyCall {
	c := &ProjectsInstancesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.setiampolicyrequest = setiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesSetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesSetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesSetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesSetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesSetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.setiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.setIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.setIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.setIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesTestIamPermissionsCall struct {
	s                         *Service
	resource                  string
	testiampermissionsrequest *TestIamPermissionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// TestIamPermissions: Returns permissions that the caller has on the specified
// instance resource. Attempting this RPC on a non-existent Cloud Spanner
// instance resource will result in a NOT_FOUND error if the user has
// `spanner.instances.list` permission on the containing Google Cloud Project.
// Otherwise returns an empty set of permissions.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which permissions are
//     being tested. The format is `projects//instances/` for instance resources
//     and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsInstancesTestIamPermissionsCall {
	c := &ProjectsInstancesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.testiampermissionsrequest = testiampermissionsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsInstancesTestIamPermissionsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesTestIamPermissionsCall) Context(ctx context.Context) *ProjectsInstancesTestIamPermissionsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesTestIamPermissionsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.testiampermissionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.testIamPermissions", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.testIamPermissions" call.
// Any non-2xx status code is an error. Response headers are in either
// *TestIamPermissionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &TestIamPermissionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.testIamPermissions", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupOperationsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists the backup long-running operations in the given instance. A
// backup operation has a name of the form
// `projects//instances//backups//operations/`. The long-running operation
// metadata field type `metadata.type_url` describes the type of the metadata.
// Operations returned include those that have completed/failed/canceled within
// the last 7 days, and pending operations. Operations returned are ordered by
// `operation.metadata.value.progress.start_time` in descending order starting
// from the most recently started operation.
//
//   - parent: The instance of the backup operations. Values are of the form
//     `projects/{project}/instances/{instance}`.
func (r *ProjectsInstancesBackupOperationsService) List(parent string) *ProjectsInstancesBackupOperationsListCall {
	c := &ProjectsInstancesBackupOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": An expression that filters the
// list of returned backup operations. A filter expression consists of a field
// name, a comparison operator, and a value for filtering. The value must be a
// string, a number, or a boolean. The comparison operator must be one of: `<`,
// `>`, `<=`, `>=`, `!=`, `=`, or `:`. Colon `:` is the contains operator.
// Filter rules are not case sensitive. The following fields in the operation
// are eligible for filtering: * `name` - The name of the long-running
// operation * `done` - False if the operation is in progress, else true. *
// `metadata.@type` - the type of metadata. For example, the type string for
// CreateBackupMetadata is
// `type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata`.
// * `metadata.` - any field in metadata.value. `metadata.@type` must be
// specified first if filtering on metadata fields. * `error` - Error
// associated with the long-running operation. * `response.@type` - the type of
// response. * `response.` - any field in response.value. You can combine
// multiple expressions by enclosing each expression in parentheses. By
// default, expressions are combined with AND logic, but you can specify AND,
// OR, and NOT logic explicitly. Here are a few examples: * `done:true` - The
// operation is complete. *
// `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CreateB
// ackupMetadata) AND` \ `metadata.database:prod` - Returns operations where: *
// The operation's metadata type is CreateBackupMetadata. * The source database
// name of backup contains the string "prod". *
// `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CreateB
// ackupMetadata) AND` \ `(metadata.name:howl) AND` \
// `(metadata.progress.start_time < \"2018-03-28T14:50:00Z\") AND` \
// `(error:*)` - Returns operations where: * The operation's metadata type is
// CreateBackupMetadata. * The backup name contains the string "howl". * The
// operation started before 2018-03-28T14:50:00Z. * The operation resulted in
// an error. *
// `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CopyBac
// kupMetadata) AND` \ `(metadata.source_backup:test) AND` \
// `(metadata.progress.start_time < \"2022-01-18T14:50:00Z\") AND` \
// `(error:*)` - Returns operations where: * The operation's metadata type is
// CopyBackupMetadata. * The source backup name contains the string "test". *
// The operation started before 2022-01-18T14:50:00Z. * The operation resulted
// in an error. *
// `((metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.Create
// BackupMetadata) AND` \ `(metadata.database:test_db)) OR` \
// `((metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CopyBa
// ckupMetadata) AND` \ `(metadata.source_backup:test_bkp)) AND` \ `(error:*)`
// - Returns operations where: * The operation's metadata matches either of
// criteria: * The operation's metadata type is CreateBackupMetadata AND the
// source database name of the backup contains the string "test_db" * The
// operation's metadata type is CopyBackupMetadata AND the source backup name
// contains the string "test_bkp" * The operation resulted in an error.
func (c *ProjectsInstancesBackupOperationsListCall) Filter(filter string) *ProjectsInstancesBackupOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of operations to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesBackupOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesBackupOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListBackupOperationsResponse to the same `parent` and with the same
// `filter`.
func (c *ProjectsInstancesBackupOperationsListCall) PageToken(pageToken string) *ProjectsInstancesBackupOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesBackupOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesBackupOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupOperationsListCall) Context(ctx context.Context) *ProjectsInstancesBackupOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/backupOperations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backupOperations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backupOperations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListBackupOperationsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupOperationsListCall) Do(opts ...googleapi.CallOption) (*ListBackupOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListBackupOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backupOperations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesBackupOperationsListCall) Pages(ctx context.Context, f func(*ListBackupOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesBackupsCopyCall struct {
	s                 *Service
	parent            string
	copybackuprequest *CopyBackupRequest
	urlParams_        gensupport.URLParams
	ctx_              context.Context
	header_           http.Header
}

// Copy: Starts copying a Cloud Spanner Backup. The returned backup
// long-running operation will have a name of the format
// `projects//instances//backups//operations/` and can be used to track copying
// of the backup. The operation is associated with the destination backup. The
// metadata field type is CopyBackupMetadata. The response field type is
// Backup, if successful. Cancelling the returned operation will stop the
// copying and delete the destination backup. Concurrent CopyBackup requests
// can run on the same source backup.
//
//   - parent: The name of the destination instance that will contain the backup
//     copy. Values are of the form: `projects/{project}/instances/{instance}`.
func (r *ProjectsInstancesBackupsService) Copy(parent string, copybackuprequest *CopyBackupRequest) *ProjectsInstancesBackupsCopyCall {
	c := &ProjectsInstancesBackupsCopyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.copybackuprequest = copybackuprequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsCopyCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsCopyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsCopyCall) Context(ctx context.Context) *ProjectsInstancesBackupsCopyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsCopyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsCopyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.copybackuprequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/backups:copy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.copy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.copy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsCopyCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.copy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsCreateCall struct {
	s          *Service
	parent     string
	backup     *Backup
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Create: Starts creating a new Cloud Spanner Backup. The returned backup
// long-running operation will have a name of the format
// `projects//instances//backups//operations/` and can be used to track
// creation of the backup. The metadata field type is CreateBackupMetadata. The
// response field type is Backup, if successful. Cancelling the returned
// operation will stop the creation and delete the backup. There can be only
// one pending backup creation per database. Backup creation of different
// databases can run concurrently.
//
//   - parent: The name of the instance in which the backup is created. This must
//     be the same instance that contains the database the backup is created
//     from. The backup will be stored in the locations specified in the instance
//     configuration of this instance. Values are of the form
//     `projects/{project}/instances/{instance}`.
func (r *ProjectsInstancesBackupsService) Create(parent string, backup *Backup) *ProjectsInstancesBackupsCreateCall {
	c := &ProjectsInstancesBackupsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.backup = backup
	return c
}

// BackupId sets the optional parameter "backupId": Required. The id of the
// backup to be created. The `backup_id` appended to `parent` forms the full
// backup name of the form
// `projects/{project}/instances/{instance}/backups/{backup_id}`.
func (c *ProjectsInstancesBackupsCreateCall) BackupId(backupId string) *ProjectsInstancesBackupsCreateCall {
	c.urlParams_.Set("backupId", backupId)
	return c
}

// EncryptionConfigEncryptionType sets the optional parameter
// "encryptionConfig.encryptionType": Required. The encryption type of the
// backup.
//
// Possible values:
//
//	"ENCRYPTION_TYPE_UNSPECIFIED" - Unspecified. Do not use.
//	"USE_DATABASE_ENCRYPTION" - Use the same encryption configuration as the
//
// database. This is the default option when encryption_config is empty. For
// example, if the database is using `Customer_Managed_Encryption`, the backup
// will be using the same Cloud KMS key as the database.
//
//	"GOOGLE_DEFAULT_ENCRYPTION" - Use Google default encryption.
//	"CUSTOMER_MANAGED_ENCRYPTION" - Use customer managed encryption. If
//
// specified, `kms_key_name` must contain a valid Cloud KMS key.
func (c *ProjectsInstancesBackupsCreateCall) EncryptionConfigEncryptionType(encryptionConfigEncryptionType string) *ProjectsInstancesBackupsCreateCall {
	c.urlParams_.Set("encryptionConfig.encryptionType", encryptionConfigEncryptionType)
	return c
}

// EncryptionConfigKmsKeyName sets the optional parameter
// "encryptionConfig.kmsKeyName": This field is maintained for backwards
// compatibility. For new callers, we recommend using `kms_key_names` to
// specify the KMS key. Only use `kms_key_name` if the location of the KMS key
// matches the database instance's configuration (location) exactly. For
// example, if the KMS location is in `us-central1` or `nam3`, then the
// database instance must also be in `us-central1` or `nam3`. The Cloud KMS key
// that is used to encrypt and decrypt the restored database. Set this field
// only when encryption_type is `CUSTOMER_MANAGED_ENCRYPTION`. Values are of
// the form
// `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{kms_
// key_name}`.
func (c *ProjectsInstancesBackupsCreateCall) EncryptionConfigKmsKeyName(encryptionConfigKmsKeyName string) *ProjectsInstancesBackupsCreateCall {
	c.urlParams_.Set("encryptionConfig.kmsKeyName", encryptionConfigKmsKeyName)
	return c
}

// EncryptionConfigKmsKeyNames sets the optional parameter
// "encryptionConfig.kmsKeyNames": Specifies the KMS configuration for the one
// or more keys used to protect the backup. Values are of the form
// `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{kms_
// key_name}`. The keys referenced by `kms_key_names` must fully cover all
// regions of the backup's instance configuration. Some examples: * For
// regional (single-region) instance configurations, specify a regional
// location KMS key. * For multi-region instance configurations of type
// `GOOGLE_MANAGED`, either specify a multi-region location KMS key or multiple
// regional location KMS keys that cover all regions in the instance
// configuration. * For an instance configuration of type `USER_MANAGED`,
// specify only regional location KMS keys to cover each region in the instance
// configuration. Multi-region location KMS keys aren't supported for
// `USER_MANAGED` type instance configurations.
func (c *ProjectsInstancesBackupsCreateCall) EncryptionConfigKmsKeyNames(encryptionConfigKmsKeyNames ...string) *ProjectsInstancesBackupsCreateCall {
	c.urlParams_.SetMulti("encryptionConfig.kmsKeyNames", append([]string{}, encryptionConfigKmsKeyNames...))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsCreateCall) Context(ctx context.Context) *ProjectsInstancesBackupsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.backup)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/backups")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsCreateCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a pending or completed Backup.
//
//   - name: Name of the backup to delete. Values are of the form
//     `projects/{project}/instances/{instance}/backups/{backup}`.
func (r *ProjectsInstancesBackupsService) Delete(name string) *ProjectsInstancesBackupsDeleteCall {
	c := &ProjectsInstancesBackupsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsDeleteCall) Context(ctx context.Context) *ProjectsInstancesBackupsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets metadata on a pending or completed Backup.
//
//   - name: Name of the backup. Values are of the form
//     `projects/{project}/instances/{instance}/backups/{backup}`.
func (r *ProjectsInstancesBackupsService) Get(name string) *ProjectsInstancesBackupsGetCall {
	c := &ProjectsInstancesBackupsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesBackupsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesBackupsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsGetCall) Context(ctx context.Context) *ProjectsInstancesBackupsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Backup.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsGetCall) Do(opts ...googleapi.CallOption) (*Backup, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Backup{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsGetIamPolicyCall struct {
	s                   *Service
	resource            string
	getiampolicyrequest *GetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// GetIamPolicy: Gets the access control policy for a database or backup
// resource. Returns an empty policy if a database or backup exists but does
// not have a policy set. Authorization requires
// `spanner.databases.getIamPolicy` permission on resource. For backups,
// authorization requires `spanner.backups.getIamPolicy` permission on
// resource. For backup schedules, authorization requires
// `spanner.backupSchedules.getIamPolicy` permission on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being retrieved. The format is `projects//instances/` for instance
//     resources and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesBackupsService) GetIamPolicy(resource string, getiampolicyrequest *GetIamPolicyRequest) *ProjectsInstancesBackupsGetIamPolicyCall {
	c := &ProjectsInstancesBackupsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.getiampolicyrequest = getiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsGetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsGetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsGetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesBackupsGetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsGetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.getiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.getIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.getIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.getIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists completed and pending backups. Backups returned are ordered by
// `create_time` in descending order, starting from the most recent
// `create_time`.
//
//   - parent: The instance to list backups from. Values are of the form
//     `projects/{project}/instances/{instance}`.
func (r *ProjectsInstancesBackupsService) List(parent string) *ProjectsInstancesBackupsListCall {
	c := &ProjectsInstancesBackupsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": An expression that filters the
// list of returned backups. A filter expression consists of a field name, a
// comparison operator, and a value for filtering. The value must be a string,
// a number, or a boolean. The comparison operator must be one of: `<`, `>`,
// `<=`, `>=`, `!=`, `=`, or `:`. Colon `:` is the contains operator. Filter
// rules are not case sensitive. The following fields in the Backup are
// eligible for filtering: * `name` * `database` * `state` * `create_time` (and
// values are of the format YYYY-MM-DDTHH:MM:SSZ) * `expire_time` (and values
// are of the format YYYY-MM-DDTHH:MM:SSZ) * `version_time` (and values are of
// the format YYYY-MM-DDTHH:MM:SSZ) * `size_bytes` * `backup_schedules` You can
// combine multiple expressions by enclosing each expression in parentheses. By
// default, expressions are combined with AND logic, but you can specify AND,
// OR, and NOT logic explicitly. Here are a few examples: * `name:Howl` - The
// backup's name contains the string "howl". * `database:prod` - The database's
// name contains the string "prod". * `state:CREATING` - The backup is pending
// creation. * `state:READY` - The backup is fully created and ready for use. *
// `(name:howl) AND (create_time < \"2018-03-28T14:50:00Z\")` - The backup name
// contains the string "howl" and `create_time` of the backup is before
// 2018-03-28T14:50:00Z. * `expire_time < \"2018-03-28T14:50:00Z\" - The
// backup `expire_time` is before 2018-03-28T14:50:00Z. * `size_bytes >
// 10000000000` - The backup's size is greater than 10GB *
// `backup_schedules:daily` - The backup is created from a schedule with
// "daily" in its name.
func (c *ProjectsInstancesBackupsListCall) Filter(filter string) *ProjectsInstancesBackupsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of backups to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesBackupsListCall) PageSize(pageSize int64) *ProjectsInstancesBackupsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListBackupsResponse to the same `parent` and with the same `filter`.
func (c *ProjectsInstancesBackupsListCall) PageToken(pageToken string) *ProjectsInstancesBackupsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesBackupsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesBackupsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsListCall) Context(ctx context.Context) *ProjectsInstancesBackupsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/backups")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListBackupsResponse.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesBackupsListCall) Do(opts ...googleapi.CallOption) (*ListBackupsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListBackupsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesBackupsListCall) Pages(ctx context.Context, f func(*ListBackupsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesBackupsPatchCall struct {
	s          *Service
	nameid     string
	backup     *Backup
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Patch: Updates a pending or completed Backup.
//
//   - name: Output only for the CreateBackup operation. Required for the
//     UpdateBackup operation. A globally unique identifier for the backup which
//     cannot be changed. Values are of the form
//     `projects/{project}/instances/{instance}/backups/a-z*[a-z0-9]` The final
//     segment of the name must be between 2 and 60 characters in length. The
//     backup is stored in the location(s) specified in the instance
//     configuration of the instance containing the backup, identified by the
//     prefix of the backup name of the form
//     `projects/{project}/instances/{instance}`.
func (r *ProjectsInstancesBackupsService) Patch(nameid string, backup *Backup) *ProjectsInstancesBackupsPatchCall {
	c := &ProjectsInstancesBackupsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	c.backup = backup
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. A mask
// specifying which fields (for example, `expire_time`) in the backup resource
// should be updated. This mask is relative to the backup resource, not to the
// request message. The field mask must always be specified; this prevents any
// future fields from being erased accidentally by clients that do not know
// about them.
func (c *ProjectsInstancesBackupsPatchCall) UpdateMask(updateMask string) *ProjectsInstancesBackupsPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsPatchCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsPatchCall) Context(ctx context.Context) *ProjectsInstancesBackupsPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.backup)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Backup.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsPatchCall) Do(opts ...googleapi.CallOption) (*Backup, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Backup{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsSetIamPolicyCall struct {
	s                   *Service
	resource            string
	setiampolicyrequest *SetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// SetIamPolicy: Sets the access control policy on a database or backup
// resource. Replaces any existing policy. Authorization requires
// `spanner.databases.setIamPolicy` permission on resource. For backups,
// authorization requires `spanner.backups.setIamPolicy` permission on
// resource. For backup schedules, authorization requires
// `spanner.backupSchedules.setIamPolicy` permission on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being set. The format is `projects//instances/` for instance resources and
//     `projects//instances//databases/` for databases resources.
func (r *ProjectsInstancesBackupsService) SetIamPolicy(resource string, setiampolicyrequest *SetIamPolicyRequest) *ProjectsInstancesBackupsSetIamPolicyCall {
	c := &ProjectsInstancesBackupsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.setiampolicyrequest = setiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsSetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsSetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsSetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesBackupsSetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsSetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.setiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.setIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.setIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.setIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsTestIamPermissionsCall struct {
	s                         *Service
	resource                  string
	testiampermissionsrequest *TestIamPermissionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// TestIamPermissions: Returns permissions that the caller has on the specified
// database or backup resource. Attempting this RPC on a non-existent Cloud
// Spanner database will result in a NOT_FOUND error if the user has
// `spanner.databases.list` permission on the containing Cloud Spanner
// instance. Otherwise returns an empty set of permissions. Calling this method
// on a backup that does not exist will result in a NOT_FOUND error if the user
// has `spanner.backups.list` permission on the containing instance. Calling
// this method on a backup schedule that does not exist will result in a
// NOT_FOUND error if the user has `spanner.backupSchedules.list` permission on
// the containing database.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which permissions are
//     being tested. The format is `projects//instances/` for instance resources
//     and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesBackupsService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsInstancesBackupsTestIamPermissionsCall {
	c := &ProjectsInstancesBackupsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.testiampermissionsrequest = testiampermissionsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsTestIamPermissionsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsTestIamPermissionsCall) Context(ctx context.Context) *ProjectsInstancesBackupsTestIamPermissionsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsTestIamPermissionsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.testiampermissionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.testIamPermissions", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.testIamPermissions" call.
// Any non-2xx status code is an error. Response headers are in either
// *TestIamPermissionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &TestIamPermissionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.testIamPermissions", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsOperationsCancelCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Cancel: Starts asynchronous cancellation on a long-running operation. The
// server makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation, the
// operation is not deleted; instead, it becomes an operation with an
// Operation.error value with a google.rpc.Status.code of `1`, corresponding to
// `Code.CANCELLED`.
//
// - name: The name of the operation resource to be cancelled.
func (r *ProjectsInstancesBackupsOperationsService) Cancel(name string) *ProjectsInstancesBackupsOperationsCancelCall {
	c := &ProjectsInstancesBackupsOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsOperationsCancelCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsOperationsCancelCall) Context(ctx context.Context) *ProjectsInstancesBackupsOperationsCancelCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsOperationsCancelCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsOperationsCancelCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.cancel", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.operations.cancel" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsOperationsCancelCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.cancel", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsOperationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a long-running operation. This method indicates that the
// client is no longer interested in the operation result. It does not cancel
// the operation. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`.
//
// - name: The name of the operation resource to be deleted.
func (r *ProjectsInstancesBackupsOperationsService) Delete(name string) *ProjectsInstancesBackupsOperationsDeleteCall {
	c := &ProjectsInstancesBackupsOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsOperationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsOperationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsOperationsDeleteCall) Context(ctx context.Context) *ProjectsInstancesBackupsOperationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsOperationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsOperationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.operations.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsOperationsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
// service.
//
// - name: The name of the operation resource.
func (r *ProjectsInstancesBackupsOperationsService) Get(name string) *ProjectsInstancesBackupsOperationsGetCall {
	c := &ProjectsInstancesBackupsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesBackupsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesBackupsOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsOperationsGetCall) Context(ctx context.Context) *ProjectsInstancesBackupsOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.operations.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesBackupsOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesBackupsOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the request. If
// the server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// - name: The name of the operation's parent resource.
func (r *ProjectsInstancesBackupsOperationsService) List(name string) *ProjectsInstancesBackupsOperationsListCall {
	c := &ProjectsInstancesBackupsOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list filter.
func (c *ProjectsInstancesBackupsOperationsListCall) Filter(filter string) *ProjectsInstancesBackupsOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list page
// size.
func (c *ProjectsInstancesBackupsOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesBackupsOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list page
// token.
func (c *ProjectsInstancesBackupsOperationsListCall) PageToken(pageToken string) *ProjectsInstancesBackupsOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// ReturnPartialSuccess sets the optional parameter "returnPartialSuccess":
// When set to `true`, operations that are reachable are returned as normal,
// and those that are unreachable are returned in the
// ListOperationsResponse.unreachable field. This can only be `true` when
// reading across collections. For example, when `parent` is set to
// "projects/example/locations/-". This field is not supported by default and
// will result in an `UNIMPLEMENTED` error if set unless explicitly documented
// otherwise in service or product specific documentation.
func (c *ProjectsInstancesBackupsOperationsListCall) ReturnPartialSuccess(returnPartialSuccess bool) *ProjectsInstancesBackupsOperationsListCall {
	c.urlParams_.Set("returnPartialSuccess", fmt.Sprint(returnPartialSuccess))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesBackupsOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesBackupsOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesBackupsOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesBackupsOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesBackupsOperationsListCall) Context(ctx context.Context) *ProjectsInstancesBackupsOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesBackupsOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesBackupsOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.backups.operations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOperationsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesBackupsOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.backups.operations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesBackupsOperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabaseOperationsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists database longrunning-operations. A database operation has a name
// of the form `projects//instances//databases//operations/`. The long-running
// operation metadata field type `metadata.type_url` describes the type of the
// metadata. Operations returned include those that have
// completed/failed/canceled within the last 7 days, and pending operations.
//
//   - parent: The instance of the database operations. Values are of the form
//     `projects//instances/`.
func (r *ProjectsInstancesDatabaseOperationsService) List(parent string) *ProjectsInstancesDatabaseOperationsListCall {
	c := &ProjectsInstancesDatabaseOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": An expression that filters the
// list of returned operations. A filter expression consists of a field name, a
// comparison operator, and a value for filtering. The value must be a string,
// a number, or a boolean. The comparison operator must be one of: `<`, `>`,
// `<=`, `>=`, `!=`, `=`, or `:`. Colon `:` is the contains operator. Filter
// rules are not case sensitive. The following fields in the operation are
// eligible for filtering: * `name` - The name of the long-running operation *
// `done` - False if the operation is in progress, else true. *
// `metadata.@type` - the type of metadata. For example, the type string for
// RestoreDatabaseMetadata is
// `type.googleapis.com/google.spanner.admin.database.v1.RestoreDatabaseMetadata
// `. * `metadata.` - any field in metadata.value. `metadata.@type` must be
// specified first, if filtering on metadata fields. * `error` - Error
// associated with the long-running operation. * `response.@type` - the type of
// response. * `response.` - any field in response.value. You can combine
// multiple expressions by enclosing each expression in parentheses. By
// default, expressions are combined with AND logic. However, you can specify
// AND, OR, and NOT logic explicitly. Here are a few examples: * `done:true` -
// The operation is complete. *
// `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.Restore
// DatabaseMetadata) AND` \ `(metadata.source_type:BACKUP) AND` \
// `(metadata.backup_info.backup:backup_howl) AND` \
// `(metadata.name:restored_howl) AND` \ `(metadata.progress.start_time <
// \"2018-03-28T14:50:00Z\") AND` \ `(error:*)` - Return operations where: *
// The operation's metadata type is RestoreDatabaseMetadata. * The database is
// restored from a backup. * The backup name contains "backup_howl". * The
// restored database's name contains "restored_howl". * The operation started
// before 2018-03-28T14:50:00Z. * The operation resulted in an error.
func (c *ProjectsInstancesDatabaseOperationsListCall) Filter(filter string) *ProjectsInstancesDatabaseOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of operations to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesDatabaseOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesDatabaseOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListDatabaseOperationsResponse to the same `parent` and with the same
// `filter`.
func (c *ProjectsInstancesDatabaseOperationsListCall) PageToken(pageToken string) *ProjectsInstancesDatabaseOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabaseOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabaseOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabaseOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabaseOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabaseOperationsListCall) Context(ctx context.Context) *ProjectsInstancesDatabaseOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabaseOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabaseOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/databaseOperations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databaseOperations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databaseOperations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListDatabaseOperationsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabaseOperationsListCall) Do(opts ...googleapi.CallOption) (*ListDatabaseOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListDatabaseOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databaseOperations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesDatabaseOperationsListCall) Pages(ctx context.Context, f func(*ListDatabaseOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabasesAddSplitPointsCall struct {
	s                     *Service
	database              string
	addsplitpointsrequest *AddSplitPointsRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// AddSplitPoints: Adds split points to specified tables and indexes of a
// database.
//
//   - database: The database on whose tables or indexes the split points are to
//     be added. Values are of the form `projects//instances//databases/`.
func (r *ProjectsInstancesDatabasesService) AddSplitPoints(database string, addsplitpointsrequest *AddSplitPointsRequest) *ProjectsInstancesDatabasesAddSplitPointsCall {
	c := &ProjectsInstancesDatabasesAddSplitPointsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	c.addsplitpointsrequest = addsplitpointsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesAddSplitPointsCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesAddSplitPointsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesAddSplitPointsCall) Context(ctx context.Context) *ProjectsInstancesDatabasesAddSplitPointsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesAddSplitPointsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesAddSplitPointsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.addsplitpointsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}:addSplitPoints")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.addSplitPoints", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.addSplitPoints" call.
// Any non-2xx status code is an error. Response headers are in either
// *AddSplitPointsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesAddSplitPointsCall) Do(opts ...googleapi.CallOption) (*AddSplitPointsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &AddSplitPointsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.addSplitPoints", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesChangequorumCall struct {
	s                   *Service
	name                string
	changequorumrequest *ChangeQuorumRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// Changequorum: `ChangeQuorum` is strictly restricted to databases that use
// dual-region instance configurations. Initiates a background operation to
// change the quorum of a database from dual-region mode to single-region mode
// or vice versa. The returned long-running operation has a name of the format
// `projects//instances//databases//operations/` and can be used to track
// execution of the `ChangeQuorum`. The metadata field type is
// ChangeQuorumMetadata. Authorization requires
// `spanner.databases.changequorum` permission on the resource database.
//
//   - name: Name of the database in which to apply `ChangeQuorum`. Values are of
//     the form `projects//instances//databases/`.
func (r *ProjectsInstancesDatabasesService) Changequorum(name string, changequorumrequest *ChangeQuorumRequest) *ProjectsInstancesDatabasesChangequorumCall {
	c := &ProjectsInstancesDatabasesChangequorumCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.changequorumrequest = changequorumrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesChangequorumCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesChangequorumCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesChangequorumCall) Context(ctx context.Context) *ProjectsInstancesDatabasesChangequorumCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesChangequorumCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesChangequorumCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.changequorumrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:changequorum")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.changequorum", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.changequorum" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesChangequorumCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.changequorum", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesCreateCall struct {
	s                     *Service
	parent                string
	createdatabaserequest *CreateDatabaseRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// Create: Creates a new Spanner database and starts to prepare it for serving.
// The returned long-running operation will have a name of the format
// `/operations/` and can be used to track preparation of the database. The
// metadata field type is CreateDatabaseMetadata. The response field type is
// Database, if successful.
//
//   - parent: The name of the instance that will serve the new database. Values
//     are of the form `projects//instances/`.
func (r *ProjectsInstancesDatabasesService) Create(parent string, createdatabaserequest *CreateDatabaseRequest) *ProjectsInstancesDatabasesCreateCall {
	c := &ProjectsInstancesDatabasesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.createdatabaserequest = createdatabaserequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesCreateCall) Context(ctx context.Context) *ProjectsInstancesDatabasesCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.createdatabaserequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/databases")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesCreateCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesDropDatabaseCall struct {
	s          *Service
	database   string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// DropDatabase: Drops (aka deletes) a Cloud Spanner database. Completed
// backups for the database will be retained according to their `expire_time`.
// Note: Cloud Spanner might continue to accept requests for a few seconds
// after the database has been deleted.
//
// - database: The database to be dropped.
func (r *ProjectsInstancesDatabasesService) DropDatabase(database string) *ProjectsInstancesDatabasesDropDatabaseCall {
	c := &ProjectsInstancesDatabasesDropDatabaseCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesDropDatabaseCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesDropDatabaseCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesDropDatabaseCall) Context(ctx context.Context) *ProjectsInstancesDatabasesDropDatabaseCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesDropDatabaseCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesDropDatabaseCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.dropDatabase", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.dropDatabase" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesDropDatabaseCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.dropDatabase", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the state of a Cloud Spanner database.
//
//   - name: The name of the requested database. Values are of the form
//     `projects//instances//databases/`.
func (r *ProjectsInstancesDatabasesService) Get(name string) *ProjectsInstancesDatabasesGetCall {
	c := &ProjectsInstancesDatabasesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesGetCall) Context(ctx context.Context) *ProjectsInstancesDatabasesGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Database.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesGetCall) Do(opts ...googleapi.CallOption) (*Database, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Database{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesGetDdlCall struct {
	s            *Service
	database     string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetDdl: Returns the schema of a Cloud Spanner database as a list of
// formatted DDL statements. This method does not show pending schema updates,
// those may be queried using the Operations API.
//
//   - database: The database whose schema we wish to get. Values are of the form
//     `projects//instances//databases/`.
func (r *ProjectsInstancesDatabasesService) GetDdl(database string) *ProjectsInstancesDatabasesGetDdlCall {
	c := &ProjectsInstancesDatabasesGetDdlCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesGetDdlCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesGetDdlCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesGetDdlCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesGetDdlCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesGetDdlCall) Context(ctx context.Context) *ProjectsInstancesDatabasesGetDdlCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesGetDdlCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesGetDdlCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}/ddl")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.getDdl", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.getDdl" call.
// Any non-2xx status code is an error. Response headers are in either
// *GetDatabaseDdlResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesGetDdlCall) Do(opts ...googleapi.CallOption) (*GetDatabaseDdlResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &GetDatabaseDdlResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.getDdl", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesGetIamPolicyCall struct {
	s                   *Service
	resource            string
	getiampolicyrequest *GetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// GetIamPolicy: Gets the access control policy for a database or backup
// resource. Returns an empty policy if a database or backup exists but does
// not have a policy set. Authorization requires
// `spanner.databases.getIamPolicy` permission on resource. For backups,
// authorization requires `spanner.backups.getIamPolicy` permission on
// resource. For backup schedules, authorization requires
// `spanner.backupSchedules.getIamPolicy` permission on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being retrieved. The format is `projects//instances/` for instance
//     resources and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesDatabasesService) GetIamPolicy(resource string, getiampolicyrequest *GetIamPolicyRequest) *ProjectsInstancesDatabasesGetIamPolicyCall {
	c := &ProjectsInstancesDatabasesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.getiampolicyrequest = getiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesGetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesGetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesGetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesDatabasesGetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesGetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.getiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.getIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.getIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.getIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesGetScansCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetScans: Request a specific scan with Database-specific data for Cloud Key
// Visualizer.
//
//   - name: The unique name of the scan containing the requested information,
//     specific to the Database service implementing this interface.
func (r *ProjectsInstancesDatabasesService) GetScans(name string) *ProjectsInstancesDatabasesGetScansCall {
	c := &ProjectsInstancesDatabasesGetScansCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// EndTime sets the optional parameter "endTime": The upper bound for the time
// range to retrieve Scan data for.
func (c *ProjectsInstancesDatabasesGetScansCall) EndTime(endTime string) *ProjectsInstancesDatabasesGetScansCall {
	c.urlParams_.Set("endTime", endTime)
	return c
}

// StartTime sets the optional parameter "startTime": These fields restrict the
// Database-specific information returned in the `Scan.data` field. If a `View`
// is provided that does not include the `Scan.data` field, these are ignored.
// This range of time must be entirely contained within the defined time range
// of the targeted scan. The lower bound for the time range to retrieve Scan
// data for.
func (c *ProjectsInstancesDatabasesGetScansCall) StartTime(startTime string) *ProjectsInstancesDatabasesGetScansCall {
	c.urlParams_.Set("startTime", startTime)
	return c
}

// View sets the optional parameter "view": Specifies which parts of the Scan
// should be returned in the response. Note, if left unspecified, the FULL view
// is assumed.
//
// Possible values:
//
//	"VIEW_UNSPECIFIED" - Not specified, equivalent to SUMMARY.
//	"SUMMARY" - Server responses only include `name`, `details`, `start_time`
//
// and `end_time`. The default value. Note, the ListScans method may only use
// this view type, others view types are not supported.
//
//	"FULL" - Full representation of the scan is returned in the server
//
// response, including `data`.
func (c *ProjectsInstancesDatabasesGetScansCall) View(view string) *ProjectsInstancesDatabasesGetScansCall {
	c.urlParams_.Set("view", view)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesGetScansCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesGetScansCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesGetScansCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesGetScansCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesGetScansCall) Context(ctx context.Context) *ProjectsInstancesDatabasesGetScansCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesGetScansCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesGetScansCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/scans")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.getScans", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.getScans" call.
// Any non-2xx status code is an error. Response headers are in either
// *Scan.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesGetScansCall) Do(opts ...googleapi.CallOption) (*Scan, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Scan{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.getScans", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists Cloud Spanner databases.
//
//   - parent: The instance whose databases should be listed. Values are of the
//     form `projects//instances/`.
func (r *ProjectsInstancesDatabasesService) List(parent string) *ProjectsInstancesDatabasesListCall {
	c := &ProjectsInstancesDatabasesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": Number of databases to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesDatabasesListCall) PageSize(pageSize int64) *ProjectsInstancesDatabasesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListDatabasesResponse.
func (c *ProjectsInstancesDatabasesListCall) PageToken(pageToken string) *ProjectsInstancesDatabasesListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesListCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesListCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesListCall) Context(ctx context.Context) *ProjectsInstancesDatabasesListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/databases")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListDatabasesResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesListCall) Do(opts ...googleapi.CallOption) (*ListDatabasesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListDatabasesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesDatabasesListCall) Pages(ctx context.Context, f func(*ListDatabasesResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabasesPatchCall struct {
	s          *Service
	name       string
	database   *Database
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Patch: Updates a Cloud Spanner database. The returned long-running operation
// can be used to track the progress of updating the database. If the named
// database does not exist, returns `NOT_FOUND`. While the operation is
// pending: * The database's reconciling field is set to true. * Cancelling the
// operation is best-effort. If the cancellation succeeds, the operation
// metadata's cancel_time is set, the updates are reverted, and the operation
// terminates with a `CANCELLED` status. * New UpdateDatabase requests will
// return a `FAILED_PRECONDITION` error until the pending operation is done
// (returns successfully or with error). * Reading the database via the API
// continues to give the pre-request values. Upon completion of the returned
// operation: * The new values are in effect and readable via the API. * The
// database's reconciling field becomes false. The returned long-running
// operation will have a name of the format
// `projects//instances//databases//operations/` and can be used to track the
// database modification. The metadata field type is UpdateDatabaseMetadata.
// The response field type is Database, if successful.
//
//   - name: The name of the database. Values are of the form
//     `projects//instances//databases/`, where “ is as specified in the `CREATE
//     DATABASE` statement. This name can be passed to other API methods to
//     identify the database.
func (r *ProjectsInstancesDatabasesService) Patch(name string, database *Database) *ProjectsInstancesDatabasesPatchCall {
	c := &ProjectsInstancesDatabasesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.database = database
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. The list of
// fields to update. Currently, only `enable_drop_protection` field can be
// updated.
func (c *ProjectsInstancesDatabasesPatchCall) UpdateMask(updateMask string) *ProjectsInstancesDatabasesPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesPatchCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesPatchCall) Context(ctx context.Context) *ProjectsInstancesDatabasesPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.database)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesRestoreCall struct {
	s                      *Service
	parent                 string
	restoredatabaserequest *RestoreDatabaseRequest
	urlParams_             gensupport.URLParams
	ctx_                   context.Context
	header_                http.Header
}

// Restore: Create a new database by restoring from a completed backup. The new
// database must be in the same project and in an instance with the same
// instance configuration as the instance containing the backup. The returned
// database long-running operation has a name of the format
// `projects//instances//databases//operations/`, and can be used to track the
// progress of the operation, and to cancel it. The metadata field type is
// RestoreDatabaseMetadata. The response type is Database, if successful.
// Cancelling the returned operation will stop the restore and delete the
// database. There can be only one database being restored into an instance at
// a time. Once the restore operation completes, a new restore operation can be
// initiated, without waiting for the optimize operation associated with the
// first restore to complete.
//
//   - parent: The name of the instance in which to create the restored database.
//     This instance must be in the same project and have the same instance
//     configuration as the instance containing the source backup. Values are of
//     the form `projects//instances/`.
func (r *ProjectsInstancesDatabasesService) Restore(parent string, restoredatabaserequest *RestoreDatabaseRequest) *ProjectsInstancesDatabasesRestoreCall {
	c := &ProjectsInstancesDatabasesRestoreCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.restoredatabaserequest = restoredatabaserequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesRestoreCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesRestoreCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesRestoreCall) Context(ctx context.Context) *ProjectsInstancesDatabasesRestoreCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesRestoreCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesRestoreCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.restoredatabaserequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/databases:restore")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.restore", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.restore" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesRestoreCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.restore", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSetIamPolicyCall struct {
	s                   *Service
	resource            string
	setiampolicyrequest *SetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// SetIamPolicy: Sets the access control policy on a database or backup
// resource. Replaces any existing policy. Authorization requires
// `spanner.databases.setIamPolicy` permission on resource. For backups,
// authorization requires `spanner.backups.setIamPolicy` permission on
// resource. For backup schedules, authorization requires
// `spanner.backupSchedules.setIamPolicy` permission on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being set. The format is `projects//instances/` for instance resources and
//     `projects//instances//databases/` for databases resources.
func (r *ProjectsInstancesDatabasesService) SetIamPolicy(resource string, setiampolicyrequest *SetIamPolicyRequest) *ProjectsInstancesDatabasesSetIamPolicyCall {
	c := &ProjectsInstancesDatabasesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.setiampolicyrequest = setiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.setiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.setIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.setIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.setIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesTestIamPermissionsCall struct {
	s                         *Service
	resource                  string
	testiampermissionsrequest *TestIamPermissionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// TestIamPermissions: Returns permissions that the caller has on the specified
// database or backup resource. Attempting this RPC on a non-existent Cloud
// Spanner database will result in a NOT_FOUND error if the user has
// `spanner.databases.list` permission on the containing Cloud Spanner
// instance. Otherwise returns an empty set of permissions. Calling this method
// on a backup that does not exist will result in a NOT_FOUND error if the user
// has `spanner.backups.list` permission on the containing instance. Calling
// this method on a backup schedule that does not exist will result in a
// NOT_FOUND error if the user has `spanner.backupSchedules.list` permission on
// the containing database.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which permissions are
//     being tested. The format is `projects//instances/` for instance resources
//     and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesDatabasesService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsInstancesDatabasesTestIamPermissionsCall {
	c := &ProjectsInstancesDatabasesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.testiampermissionsrequest = testiampermissionsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesTestIamPermissionsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesTestIamPermissionsCall) Context(ctx context.Context) *ProjectsInstancesDatabasesTestIamPermissionsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesTestIamPermissionsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.testiampermissionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.testIamPermissions", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.testIamPermissions" call.
// Any non-2xx status code is an error. Response headers are in either
// *TestIamPermissionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &TestIamPermissionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.testIamPermissions", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesUpdateDdlCall struct {
	s                        *Service
	database                 string
	updatedatabaseddlrequest *UpdateDatabaseDdlRequest
	urlParams_               gensupport.URLParams
	ctx_                     context.Context
	header_                  http.Header
}

// UpdateDdl: Updates the schema of a Cloud Spanner database by
// creating/altering/dropping tables, columns, indexes, etc. The returned
// long-running operation will have a name of the format `/operations/` and can
// be used to track execution of the schema changes. The metadata field type is
// UpdateDatabaseDdlMetadata. The operation has no response.
//
// - database: The database to update.
func (r *ProjectsInstancesDatabasesService) UpdateDdl(database string, updatedatabaseddlrequest *UpdateDatabaseDdlRequest) *ProjectsInstancesDatabasesUpdateDdlCall {
	c := &ProjectsInstancesDatabasesUpdateDdlCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	c.updatedatabaseddlrequest = updatedatabaseddlrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesUpdateDdlCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesUpdateDdlCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesUpdateDdlCall) Context(ctx context.Context) *ProjectsInstancesDatabasesUpdateDdlCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesUpdateDdlCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesUpdateDdlCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.updatedatabaseddlrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}/ddl")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.updateDdl", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.updateDdl" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesUpdateDdlCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.updateDdl", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesCreateCall struct {
	s              *Service
	parent         string
	backupschedule *BackupSchedule
	urlParams_     gensupport.URLParams
	ctx_           context.Context
	header_        http.Header
}

// Create: Creates a new backup schedule.
//
// - parent: The name of the database that this backup schedule applies to.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) Create(parent string, backupschedule *BackupSchedule) *ProjectsInstancesDatabasesBackupSchedulesCreateCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.backupschedule = backupschedule
	return c
}

// BackupScheduleId sets the optional parameter "backupScheduleId": Required.
// The Id to use for the backup schedule. The `backup_schedule_id` appended to
// `parent` forms the full backup schedule name of the form
// `projects//instances//databases//backupSchedules/`.
func (c *ProjectsInstancesDatabasesBackupSchedulesCreateCall) BackupScheduleId(backupScheduleId string) *ProjectsInstancesDatabasesBackupSchedulesCreateCall {
	c.urlParams_.Set("backupScheduleId", backupScheduleId)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesCreateCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.backupschedule)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/backupSchedules")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *BackupSchedule.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesCreateCall) Do(opts ...googleapi.CallOption) (*BackupSchedule, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &BackupSchedule{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a backup schedule.
//
//   - name: The name of the schedule to delete. Values are of the form
//     `projects//instances//databases//backupSchedules/`.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) Delete(name string) *ProjectsInstancesDatabasesBackupSchedulesDeleteCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesDeleteCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets backup schedule for the input schedule name.
//
//   - name: The name of the schedule to retrieve. Values are of the form
//     `projects//instances//databases//backupSchedules/`.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) Get(name string) *ProjectsInstancesDatabasesBackupSchedulesGetCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesBackupSchedulesGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *BackupSchedule.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetCall) Do(opts ...googleapi.CallOption) (*BackupSchedule, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &BackupSchedule{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall struct {
	s                   *Service
	resource            string
	getiampolicyrequest *GetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// GetIamPolicy: Gets the access control policy for a database or backup
// resource. Returns an empty policy if a database or backup exists but does
// not have a policy set. Authorization requires
// `spanner.databases.getIamPolicy` permission on resource. For backups,
// authorization requires `spanner.backups.getIamPolicy` permission on
// resource. For backup schedules, authorization requires
// `spanner.backupSchedules.getIamPolicy` permission on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being retrieved. The format is `projects//instances/` for instance
//     resources and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) GetIamPolicy(resource string, getiampolicyrequest *GetIamPolicyRequest) *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.getiampolicyrequest = getiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.getiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.getIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.getIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.getIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists all the backup schedules for the database.
//
//   - parent: Database is the parent resource whose backup schedules should be
//     listed. Values are of the form projects//instances//databases/.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) List(parent string) *ProjectsInstancesDatabasesBackupSchedulesListCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": Number of backup schedules
// to be returned in the response. If 0 or less, defaults to the server's
// maximum allowed page size.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) PageSize(pageSize int64) *ProjectsInstancesDatabasesBackupSchedulesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListBackupSchedulesResponse to the same `parent`.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) PageToken(pageToken string) *ProjectsInstancesDatabasesBackupSchedulesListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesBackupSchedulesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/backupSchedules")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListBackupSchedulesResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) Do(opts ...googleapi.CallOption) (*ListBackupSchedulesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListBackupSchedulesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesDatabasesBackupSchedulesListCall) Pages(ctx context.Context, f func(*ListBackupSchedulesResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabasesBackupSchedulesPatchCall struct {
	s              *Service
	nameid         string
	backupschedule *BackupSchedule
	urlParams_     gensupport.URLParams
	ctx_           context.Context
	header_        http.Header
}

// Patch: Updates a backup schedule.
//
//   - name: Identifier. Output only for the CreateBackupSchedule operation.
//     Required for the UpdateBackupSchedule operation. A globally unique
//     identifier for the backup schedule which cannot be changed. Values are of
//     the form `projects//instances//databases//backupSchedules/a-z*[a-z0-9]`
//     The final segment of the name must be between 2 and 60 characters in
//     length.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) Patch(nameid string, backupschedule *BackupSchedule) *ProjectsInstancesDatabasesBackupSchedulesPatchCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	c.backupschedule = backupschedule
	return c
}

// UpdateMask sets the optional parameter "updateMask": Required. A mask
// specifying which fields in the BackupSchedule resource should be updated.
// This mask is relative to the BackupSchedule resource, not to the request
// message. The field mask must always be specified; this prevents any future
// fields from being erased accidentally.
func (c *ProjectsInstancesDatabasesBackupSchedulesPatchCall) UpdateMask(updateMask string) *ProjectsInstancesDatabasesBackupSchedulesPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesPatchCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesPatchCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.backupschedule)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *BackupSchedule.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesPatchCall) Do(opts ...googleapi.CallOption) (*BackupSchedule, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &BackupSchedule{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall struct {
	s                   *Service
	resource            string
	setiampolicyrequest *SetIamPolicyRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// SetIamPolicy: Sets the access control policy on a database or backup
// resource. Replaces any existing policy. Authorization requires
// `spanner.databases.setIamPolicy` permission on resource. For backups,
// authorization requires `spanner.backups.setIamPolicy` permission on
// resource. For backup schedules, authorization requires
// `spanner.backupSchedules.setIamPolicy` permission on resource.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which the policy is
//     being set. The format is `projects//instances/` for instance resources and
//     `projects//instances//databases/` for databases resources.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) SetIamPolicy(resource string, setiampolicyrequest *SetIamPolicyRequest) *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.setiampolicyrequest = setiampolicyrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.setiampolicyrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.setIamPolicy", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.setIamPolicy" call.
// Any non-2xx status code is an error. Response headers are in either
// *Policy.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Policy{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.setIamPolicy", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall struct {
	s                         *Service
	resource                  string
	testiampermissionsrequest *TestIamPermissionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// TestIamPermissions: Returns permissions that the caller has on the specified
// database or backup resource. Attempting this RPC on a non-existent Cloud
// Spanner database will result in a NOT_FOUND error if the user has
// `spanner.databases.list` permission on the containing Cloud Spanner
// instance. Otherwise returns an empty set of permissions. Calling this method
// on a backup that does not exist will result in a NOT_FOUND error if the user
// has `spanner.backups.list` permission on the containing instance. Calling
// this method on a backup schedule that does not exist will result in a
// NOT_FOUND error if the user has `spanner.backupSchedules.list` permission on
// the containing database.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which permissions are
//     being tested. The format is `projects//instances/` for instance resources
//     and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesDatabasesBackupSchedulesService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall {
	c := &ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.testiampermissionsrequest = testiampermissionsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall) Context(ctx context.Context) *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.testiampermissionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.testIamPermissions", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.backupSchedules.testIamPermissions" call.
// Any non-2xx status code is an error. Response headers are in either
// *TestIamPermissionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesBackupSchedulesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &TestIamPermissionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.backupSchedules.testIamPermissions", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesDatabaseRolesListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists Cloud Spanner database roles.
//
//   - parent: The database whose roles should be listed. Values are of the form
//     `projects//instances//databases/`.
func (r *ProjectsInstancesDatabasesDatabaseRolesService) List(parent string) *ProjectsInstancesDatabasesDatabaseRolesListCall {
	c := &ProjectsInstancesDatabasesDatabaseRolesListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": Number of database roles to
// be returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) PageSize(pageSize int64) *ProjectsInstancesDatabasesDatabaseRolesListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListDatabaseRolesResponse.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) PageToken(pageToken string) *ProjectsInstancesDatabasesDatabaseRolesListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesDatabaseRolesListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesDatabaseRolesListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) Context(ctx context.Context) *ProjectsInstancesDatabasesDatabaseRolesListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/databaseRoles")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.databaseRoles.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.databaseRoles.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListDatabaseRolesResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) Do(opts ...googleapi.CallOption) (*ListDatabaseRolesResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListDatabaseRolesResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.databaseRoles.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesDatabasesDatabaseRolesListCall) Pages(ctx context.Context, f func(*ListDatabaseRolesResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall struct {
	s                         *Service
	resource                  string
	testiampermissionsrequest *TestIamPermissionsRequest
	urlParams_                gensupport.URLParams
	ctx_                      context.Context
	header_                   http.Header
}

// TestIamPermissions: Returns permissions that the caller has on the specified
// database or backup resource. Attempting this RPC on a non-existent Cloud
// Spanner database will result in a NOT_FOUND error if the user has
// `spanner.databases.list` permission on the containing Cloud Spanner
// instance. Otherwise returns an empty set of permissions. Calling this method
// on a backup that does not exist will result in a NOT_FOUND error if the user
// has `spanner.backups.list` permission on the containing instance. Calling
// this method on a backup schedule that does not exist will result in a
// NOT_FOUND error if the user has `spanner.backupSchedules.list` permission on
// the containing database.
//
//   - resource: REQUIRED: The Cloud Spanner resource for which permissions are
//     being tested. The format is `projects//instances/` for instance resources
//     and `projects//instances//databases/` for database resources.
func (r *ProjectsInstancesDatabasesDatabaseRolesService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall {
	c := &ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.resource = resource
	c.testiampermissionsrequest = testiampermissionsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall) Context(ctx context.Context) *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.testiampermissionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"resource": c.resource,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.databaseRoles.testIamPermissions", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.databaseRoles.testIamPermissions" call.
// Any non-2xx status code is an error. Response headers are in either
// *TestIamPermissionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesDatabaseRolesTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &TestIamPermissionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.databaseRoles.testIamPermissions", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesOperationsCancelCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Cancel: Starts asynchronous cancellation on a long-running operation. The
// server makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation, the
// operation is not deleted; instead, it becomes an operation with an
// Operation.error value with a google.rpc.Status.code of `1`, corresponding to
// `Code.CANCELLED`.
//
// - name: The name of the operation resource to be cancelled.
func (r *ProjectsInstancesDatabasesOperationsService) Cancel(name string) *ProjectsInstancesDatabasesOperationsCancelCall {
	c := &ProjectsInstancesDatabasesOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesOperationsCancelCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesOperationsCancelCall) Context(ctx context.Context) *ProjectsInstancesDatabasesOperationsCancelCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesOperationsCancelCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesOperationsCancelCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.cancel", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.operations.cancel" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesOperationsCancelCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.cancel", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesOperationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a long-running operation. This method indicates that the
// client is no longer interested in the operation result. It does not cancel
// the operation. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`.
//
// - name: The name of the operation resource to be deleted.
func (r *ProjectsInstancesDatabasesOperationsService) Delete(name string) *ProjectsInstancesDatabasesOperationsDeleteCall {
	c := &ProjectsInstancesDatabasesOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesOperationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesOperationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesOperationsDeleteCall) Context(ctx context.Context) *ProjectsInstancesDatabasesOperationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesOperationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesOperationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.operations.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesOperationsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
// service.
//
// - name: The name of the operation resource.
func (r *ProjectsInstancesDatabasesOperationsService) Get(name string) *ProjectsInstancesDatabasesOperationsGetCall {
	c := &ProjectsInstancesDatabasesOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesOperationsGetCall) Context(ctx context.Context) *ProjectsInstancesDatabasesOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.operations.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the request. If
// the server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// - name: The name of the operation's parent resource.
func (r *ProjectsInstancesDatabasesOperationsService) List(name string) *ProjectsInstancesDatabasesOperationsListCall {
	c := &ProjectsInstancesDatabasesOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list filter.
func (c *ProjectsInstancesDatabasesOperationsListCall) Filter(filter string) *ProjectsInstancesDatabasesOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list page
// size.
func (c *ProjectsInstancesDatabasesOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesDatabasesOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list page
// token.
func (c *ProjectsInstancesDatabasesOperationsListCall) PageToken(pageToken string) *ProjectsInstancesDatabasesOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// ReturnPartialSuccess sets the optional parameter "returnPartialSuccess":
// When set to `true`, operations that are reachable are returned as normal,
// and those that are unreachable are returned in the
// ListOperationsResponse.unreachable field. This can only be `true` when
// reading across collections. For example, when `parent` is set to
// "projects/example/locations/-". This field is not supported by default and
// will result in an `UNIMPLEMENTED` error if set unless explicitly documented
// otherwise in service or product specific documentation.
func (c *ProjectsInstancesDatabasesOperationsListCall) ReturnPartialSuccess(returnPartialSuccess bool) *ProjectsInstancesDatabasesOperationsListCall {
	c.urlParams_.Set("returnPartialSuccess", fmt.Sprint(returnPartialSuccess))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesOperationsListCall) Context(ctx context.Context) *ProjectsInstancesDatabasesOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.operations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOperationsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.operations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesDatabasesOperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabasesSessionsAdaptMessageCall struct {
	s                   *Service
	name                string
	adaptmessagerequest *AdaptMessageRequest
	urlParams_          gensupport.URLParams
	ctx_                context.Context
	header_             http.Header
}

// AdaptMessage: Handles a single message from the client and returns the
// result as a stream. The server will interpret the message frame and respond
// with message frames to the client.
//
// - name: The database session in which the adapter request is processed.
func (r *ProjectsInstancesDatabasesSessionsService) AdaptMessage(name string, adaptmessagerequest *AdaptMessageRequest) *ProjectsInstancesDatabasesSessionsAdaptMessageCall {
	c := &ProjectsInstancesDatabasesSessionsAdaptMessageCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.adaptmessagerequest = adaptmessagerequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsAdaptMessageCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsAdaptMessageCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsAdaptMessageCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsAdaptMessageCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsAdaptMessageCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsAdaptMessageCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.adaptmessagerequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:adaptMessage")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.adaptMessage", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.adaptMessage" call.
// Any non-2xx status code is an error. Response headers are in either
// *AdaptMessageResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsAdaptMessageCall) Do(opts ...googleapi.CallOption) (*AdaptMessageResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &AdaptMessageResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.adaptMessage", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsAdapterCall struct {
	s              *Service
	parent         string
	adaptersession *AdapterSession
	urlParams_     gensupport.URLParams
	ctx_           context.Context
	header_        http.Header
}

// Adapter: Creates a new session to be used for requests made by the adapter.
// A session identifies a specific incarnation of a database resource and is
// meant to be reused across many `AdaptMessage` calls.
//
// - parent: The database in which the new session is created.
func (r *ProjectsInstancesDatabasesSessionsService) Adapter(parent string, adaptersession *AdapterSession) *ProjectsInstancesDatabasesSessionsAdapterCall {
	c := &ProjectsInstancesDatabasesSessionsAdapterCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.adaptersession = adaptersession
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsAdapterCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsAdapterCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsAdapterCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsAdapterCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsAdapterCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsAdapterCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.adaptersession)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/sessions:adapter")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.adapter", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.adapter" call.
// Any non-2xx status code is an error. Response headers are in either
// *AdapterSession.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsAdapterCall) Do(opts ...googleapi.CallOption) (*AdapterSession, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &AdapterSession{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.adapter", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsBatchCreateCall struct {
	s                          *Service
	database                   string
	batchcreatesessionsrequest *BatchCreateSessionsRequest
	urlParams_                 gensupport.URLParams
	ctx_                       context.Context
	header_                    http.Header
}

// BatchCreate: Creates multiple new sessions. This API can be used to
// initialize a session cache on the clients. See https://goo.gl/TgSFN2 for
// best practices on session cache management.
//
// - database: The database in which the new sessions are created.
func (r *ProjectsInstancesDatabasesSessionsService) BatchCreate(database string, batchcreatesessionsrequest *BatchCreateSessionsRequest) *ProjectsInstancesDatabasesSessionsBatchCreateCall {
	c := &ProjectsInstancesDatabasesSessionsBatchCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	c.batchcreatesessionsrequest = batchcreatesessionsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsBatchCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsBatchCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsBatchCreateCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsBatchCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsBatchCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsBatchCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.batchcreatesessionsrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}/sessions:batchCreate")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.batchCreate", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.batchCreate" call.
// Any non-2xx status code is an error. Response headers are in either
// *BatchCreateSessionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsBatchCreateCall) Do(opts ...googleapi.CallOption) (*BatchCreateSessionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &BatchCreateSessionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.batchCreate", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsBatchWriteCall struct {
	s                 *Service
	session           string
	batchwriterequest *BatchWriteRequest
	urlParams_        gensupport.URLParams
	ctx_              context.Context
	header_           http.Header
}

// BatchWrite: Batches the supplied mutation groups in a collection of
// efficient transactions. All mutations in a group are committed atomically.
// However, mutations across groups can be committed non-atomically in an
// unspecified order and thus, they must be independent of each other. Partial
// failure is possible, that is, some groups might have been committed
// successfully, while some might have failed. The results of individual
// batches are streamed into the response as the batches are applied.
// `BatchWrite` requests are not replay protected, meaning that each mutation
// group can be applied more than once. Replays of non-idempotent mutations can
// have undesirable effects. For example, replays of an insert mutation can
// produce an already exists error or if you use generated or commit
// timestamp-based keys, it can result in additional rows being added to the
// mutation's table. We recommend structuring your mutation groups to be
// idempotent to avoid this issue.
//
// - session: The session in which the batch request is to be run.
func (r *ProjectsInstancesDatabasesSessionsService) BatchWrite(session string, batchwriterequest *BatchWriteRequest) *ProjectsInstancesDatabasesSessionsBatchWriteCall {
	c := &ProjectsInstancesDatabasesSessionsBatchWriteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.batchwriterequest = batchwriterequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsBatchWriteCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsBatchWriteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsBatchWriteCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsBatchWriteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsBatchWriteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsBatchWriteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.batchwriterequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:batchWrite")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.batchWrite", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.batchWrite" call.
// Any non-2xx status code is an error. Response headers are in either
// *BatchWriteResponse.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsBatchWriteCall) Do(opts ...googleapi.CallOption) (*BatchWriteResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &BatchWriteResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.batchWrite", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsBeginTransactionCall struct {
	s                       *Service
	session                 string
	begintransactionrequest *BeginTransactionRequest
	urlParams_              gensupport.URLParams
	ctx_                    context.Context
	header_                 http.Header
}

// BeginTransaction: Begins a new transaction. This step can often be skipped:
// Read, ExecuteSql and Commit can begin a new transaction as a side-effect.
//
// - session: The session in which the transaction runs.
func (r *ProjectsInstancesDatabasesSessionsService) BeginTransaction(session string, begintransactionrequest *BeginTransactionRequest) *ProjectsInstancesDatabasesSessionsBeginTransactionCall {
	c := &ProjectsInstancesDatabasesSessionsBeginTransactionCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.begintransactionrequest = begintransactionrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsBeginTransactionCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsBeginTransactionCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsBeginTransactionCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsBeginTransactionCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsBeginTransactionCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsBeginTransactionCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.begintransactionrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:beginTransaction")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.beginTransaction", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.beginTransaction" call.
// Any non-2xx status code is an error. Response headers are in either
// *Transaction.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsBeginTransactionCall) Do(opts ...googleapi.CallOption) (*Transaction, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Transaction{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.beginTransaction", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsCommitCall struct {
	s             *Service
	session       string
	commitrequest *CommitRequest
	urlParams_    gensupport.URLParams
	ctx_          context.Context
	header_       http.Header
}

// Commit: Commits a transaction. The request includes the mutations to be
// applied to rows in the database. `Commit` might return an `ABORTED` error.
// This can occur at any time; commonly, the cause is conflicts with concurrent
// transactions. However, it can also happen for a variety of other reasons. If
// `Commit` returns `ABORTED`, the caller should retry the transaction from the
// beginning, reusing the same session. On very rare occasions, `Commit` might
// return `UNKNOWN`. This can happen, for example, if the client job
// experiences a 1+ hour networking failure. At that point, Cloud Spanner has
// lost track of the transaction outcome and we recommend that you perform
// another read from the database to see the state of things as they are now.
//
// - session: The session in which the transaction to be committed is running.
func (r *ProjectsInstancesDatabasesSessionsService) Commit(session string, commitrequest *CommitRequest) *ProjectsInstancesDatabasesSessionsCommitCall {
	c := &ProjectsInstancesDatabasesSessionsCommitCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.commitrequest = commitrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsCommitCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsCommitCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsCommitCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsCommitCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsCommitCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsCommitCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.commitrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:commit")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.commit", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.commit" call.
// Any non-2xx status code is an error. Response headers are in either
// *CommitResponse.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsCommitCall) Do(opts ...googleapi.CallOption) (*CommitResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &CommitResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.commit", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsCreateCall struct {
	s                    *Service
	database             string
	createsessionrequest *CreateSessionRequest
	urlParams_           gensupport.URLParams
	ctx_                 context.Context
	header_              http.Header
}

// Create: Creates a new session. A session can be used to perform transactions
// that read and/or modify data in a Cloud Spanner database. Sessions are meant
// to be reused for many consecutive transactions. Sessions can only execute
// one transaction at a time. To execute multiple concurrent
// read-write/write-only transactions, create multiple sessions. Note that
// standalone reads and queries use a transaction internally, and count toward
// the one transaction limit. Active sessions use additional server resources,
// so it's a good idea to delete idle and unneeded sessions. Aside from
// explicit deletes, Cloud Spanner can delete sessions when no operations are
// sent for more than an hour. If a session is deleted, requests to it return
// `NOT_FOUND`. Idle sessions can be kept alive by sending a trivial SQL query
// periodically, for example, "SELECT 1".
//
// - database: The database in which the new session is created.
func (r *ProjectsInstancesDatabasesSessionsService) Create(database string, createsessionrequest *CreateSessionRequest) *ProjectsInstancesDatabasesSessionsCreateCall {
	c := &ProjectsInstancesDatabasesSessionsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	c.createsessionrequest = createsessionrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsCreateCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.createsessionrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}/sessions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Session.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsCreateCall) Do(opts ...googleapi.CallOption) (*Session, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Session{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Ends a session, releasing server resources associated with it. This
// asynchronously triggers the cancellation of any operations that are running
// with this session.
//
// - name: The name of the session to delete.
func (r *ProjectsInstancesDatabasesSessionsService) Delete(name string) *ProjectsInstancesDatabasesSessionsDeleteCall {
	c := &ProjectsInstancesDatabasesSessionsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsDeleteCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall struct {
	s                      *Service
	session                string
	executebatchdmlrequest *ExecuteBatchDmlRequest
	urlParams_             gensupport.URLParams
	ctx_                   context.Context
	header_                http.Header
}

// ExecuteBatchDml: Executes a batch of SQL DML statements. This method allows
// many statements to be run with lower latency than submitting them
// sequentially with ExecuteSql. Statements are executed in sequential order. A
// request can succeed even if a statement fails. The
// ExecuteBatchDmlResponse.status field in the response provides information
// about the statement that failed. Clients must inspect this field to
// determine whether an error occurred. Execution stops after the first failed
// statement; the remaining statements are not executed.
//
// - session: The session in which the DML statements should be performed.
func (r *ProjectsInstancesDatabasesSessionsService) ExecuteBatchDml(session string, executebatchdmlrequest *ExecuteBatchDmlRequest) *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall {
	c := &ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.executebatchdmlrequest = executebatchdmlrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.executebatchdmlrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:executeBatchDml")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.executeBatchDml", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.executeBatchDml" call.
// Any non-2xx status code is an error. Response headers are in either
// *ExecuteBatchDmlResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsExecuteBatchDmlCall) Do(opts ...googleapi.CallOption) (*ExecuteBatchDmlResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ExecuteBatchDmlResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.executeBatchDml", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsExecuteSqlCall struct {
	s                 *Service
	session           string
	executesqlrequest *ExecuteSqlRequest
	urlParams_        gensupport.URLParams
	ctx_              context.Context
	header_           http.Header
}

// ExecuteSql: Executes an SQL statement, returning all results in a single
// reply. This method can't be used to return a result set larger than 10 MiB;
// if the query yields more data than that, the query fails with a
// `FAILED_PRECONDITION` error. Operations inside read-write transactions might
// return `ABORTED`. If this occurs, the application should restart the
// transaction from the beginning. See Transaction for more details. Larger
// result sets can be fetched in streaming fashion by calling
// ExecuteStreamingSql instead. The query string can be SQL or Graph Query
// Language (GQL)
// (https://cloud.google.com/spanner/docs/reference/standard-sql/graph-intro).
//
// - session: The session in which the SQL query should be performed.
func (r *ProjectsInstancesDatabasesSessionsService) ExecuteSql(session string, executesqlrequest *ExecuteSqlRequest) *ProjectsInstancesDatabasesSessionsExecuteSqlCall {
	c := &ProjectsInstancesDatabasesSessionsExecuteSqlCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.executesqlrequest = executesqlrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsExecuteSqlCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsExecuteSqlCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsExecuteSqlCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsExecuteSqlCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsExecuteSqlCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsExecuteSqlCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.executesqlrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:executeSql")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.executeSql", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.executeSql" call.
// Any non-2xx status code is an error. Response headers are in either
// *ResultSet.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsExecuteSqlCall) Do(opts ...googleapi.CallOption) (*ResultSet, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ResultSet{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.executeSql", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall struct {
	s                 *Service
	session           string
	executesqlrequest *ExecuteSqlRequest
	urlParams_        gensupport.URLParams
	ctx_              context.Context
	header_           http.Header
}

// ExecuteStreamingSql: Like ExecuteSql, except returns the result set as a
// stream. Unlike ExecuteSql, there is no limit on the size of the returned
// result set. However, no individual row in the result set can exceed 100 MiB,
// and no column value can exceed 10 MiB. The query string can be SQL or Graph
// Query Language (GQL)
// (https://cloud.google.com/spanner/docs/reference/standard-sql/graph-intro).
//
// - session: The session in which the SQL query should be performed.
func (r *ProjectsInstancesDatabasesSessionsService) ExecuteStreamingSql(session string, executesqlrequest *ExecuteSqlRequest) *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall {
	c := &ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.executesqlrequest = executesqlrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.executesqlrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:executeStreamingSql")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.executeStreamingSql", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.executeStreamingSql" call.
// Any non-2xx status code is an error. Response headers are in either
// *PartialResultSet.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsExecuteStreamingSqlCall) Do(opts ...googleapi.CallOption) (*PartialResultSet, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &PartialResultSet{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.executeStreamingSql", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets a session. Returns `NOT_FOUND` if the session doesn't exist. This
// is mainly useful for determining whether a session is still alive.
//
// - name: The name of the session to retrieve.
func (r *ProjectsInstancesDatabasesSessionsService) Get(name string) *ProjectsInstancesDatabasesSessionsGetCall {
	c := &ProjectsInstancesDatabasesSessionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesSessionsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesSessionsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsGetCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Session.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsGetCall) Do(opts ...googleapi.CallOption) (*Session, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Session{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsListCall struct {
	s            *Service
	database     string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists all sessions in a given database.
//
// - database: The database in which to list sessions.
func (r *ProjectsInstancesDatabasesSessionsService) List(database string) *ProjectsInstancesDatabasesSessionsListCall {
	c := &ProjectsInstancesDatabasesSessionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.database = database
	return c
}

// Filter sets the optional parameter "filter": An expression for filtering the
// results of the request. Filter rules are case insensitive. The fields
// eligible for filtering are: * `labels.key` where key is the name of a label
// Some examples of using filters are: * `labels.env:*` --> The session has the
// label "env". * `labels.env:dev` --> The session has the label "env" and the
// value of the label contains the string "dev".
func (c *ProjectsInstancesDatabasesSessionsListCall) Filter(filter string) *ProjectsInstancesDatabasesSessionsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of sessions to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesDatabasesSessionsListCall) PageSize(pageSize int64) *ProjectsInstancesDatabasesSessionsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListSessionsResponse.
func (c *ProjectsInstancesDatabasesSessionsListCall) PageToken(pageToken string) *ProjectsInstancesDatabasesSessionsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesDatabasesSessionsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesDatabasesSessionsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsListCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+database}/sessions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"database": c.database,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListSessionsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsListCall) Do(opts ...googleapi.CallOption) (*ListSessionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListSessionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesDatabasesSessionsListCall) Pages(ctx context.Context, f func(*ListSessionsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesDatabasesSessionsPartitionQueryCall struct {
	s                     *Service
	session               string
	partitionqueryrequest *PartitionQueryRequest
	urlParams_            gensupport.URLParams
	ctx_                  context.Context
	header_               http.Header
}

// PartitionQuery: Creates a set of partition tokens that can be used to
// execute a query operation in parallel. Each of the returned partition tokens
// can be used by ExecuteStreamingSql to specify a subset of the query result
// to read. The same session and read-only transaction must be used by the
// `PartitionQueryRequest` used to create the partition tokens and the
// `ExecuteSqlRequests` that use the partition tokens. Partition tokens become
// invalid when the session used to create them is deleted, is idle for too
// long, begins a new transaction, or becomes too old. When any of these
// happen, it isn't possible to resume the query, and the whole operation must
// be restarted from the beginning.
//
// - session: The session used to create the partitions.
func (r *ProjectsInstancesDatabasesSessionsService) PartitionQuery(session string, partitionqueryrequest *PartitionQueryRequest) *ProjectsInstancesDatabasesSessionsPartitionQueryCall {
	c := &ProjectsInstancesDatabasesSessionsPartitionQueryCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.partitionqueryrequest = partitionqueryrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsPartitionQueryCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsPartitionQueryCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsPartitionQueryCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsPartitionQueryCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsPartitionQueryCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsPartitionQueryCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.partitionqueryrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:partitionQuery")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.partitionQuery", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.partitionQuery" call.
// Any non-2xx status code is an error. Response headers are in either
// *PartitionResponse.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsPartitionQueryCall) Do(opts ...googleapi.CallOption) (*PartitionResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &PartitionResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.partitionQuery", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsPartitionReadCall struct {
	s                    *Service
	session              string
	partitionreadrequest *PartitionReadRequest
	urlParams_           gensupport.URLParams
	ctx_                 context.Context
	header_              http.Header
}

// PartitionRead: Creates a set of partition tokens that can be used to execute
// a read operation in parallel. Each of the returned partition tokens can be
// used by StreamingRead to specify a subset of the read result to read. The
// same session and read-only transaction must be used by the
// `PartitionReadRequest` used to create the partition tokens and the
// `ReadRequests` that use the partition tokens. There are no ordering
// guarantees on rows returned among the returned partition tokens, or even
// within each individual `StreamingRead` call issued with a `partition_token`.
// Partition tokens become invalid when the session used to create them is
// deleted, is idle for too long, begins a new transaction, or becomes too old.
// When any of these happen, it isn't possible to resume the read, and the
// whole operation must be restarted from the beginning.
//
// - session: The session used to create the partitions.
func (r *ProjectsInstancesDatabasesSessionsService) PartitionRead(session string, partitionreadrequest *PartitionReadRequest) *ProjectsInstancesDatabasesSessionsPartitionReadCall {
	c := &ProjectsInstancesDatabasesSessionsPartitionReadCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.partitionreadrequest = partitionreadrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsPartitionReadCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsPartitionReadCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsPartitionReadCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsPartitionReadCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsPartitionReadCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsPartitionReadCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.partitionreadrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:partitionRead")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.partitionRead", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.partitionRead" call.
// Any non-2xx status code is an error. Response headers are in either
// *PartitionResponse.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsPartitionReadCall) Do(opts ...googleapi.CallOption) (*PartitionResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &PartitionResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.partitionRead", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsReadCall struct {
	s           *Service
	session     string
	readrequest *ReadRequest
	urlParams_  gensupport.URLParams
	ctx_        context.Context
	header_     http.Header
}

// Read: Reads rows from the database using key lookups and scans, as a simple
// key/value style alternative to ExecuteSql. This method can't be used to
// return a result set larger than 10 MiB; if the read matches more data than
// that, the read fails with a `FAILED_PRECONDITION` error. Reads inside
// read-write transactions might return `ABORTED`. If this occurs, the
// application should restart the transaction from the beginning. See
// Transaction for more details. Larger result sets can be yielded in streaming
// fashion by calling StreamingRead instead.
//
// - session: The session in which the read should be performed.
func (r *ProjectsInstancesDatabasesSessionsService) Read(session string, readrequest *ReadRequest) *ProjectsInstancesDatabasesSessionsReadCall {
	c := &ProjectsInstancesDatabasesSessionsReadCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.readrequest = readrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsReadCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsReadCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsReadCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsReadCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsReadCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsReadCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.readrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:read")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.read", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.read" call.
// Any non-2xx status code is an error. Response headers are in either
// *ResultSet.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsReadCall) Do(opts ...googleapi.CallOption) (*ResultSet, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ResultSet{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.read", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsRollbackCall struct {
	s               *Service
	session         string
	rollbackrequest *RollbackRequest
	urlParams_      gensupport.URLParams
	ctx_            context.Context
	header_         http.Header
}

// Rollback: Rolls back a transaction, releasing any locks it holds. It's a
// good idea to call this for any transaction that includes one or more Read or
// ExecuteSql requests and ultimately decides not to commit. `Rollback` returns
// `OK` if it successfully aborts the transaction, the transaction was already
// aborted, or the transaction isn't found. `Rollback` never returns `ABORTED`.
//
// - session: The session in which the transaction to roll back is running.
func (r *ProjectsInstancesDatabasesSessionsService) Rollback(session string, rollbackrequest *RollbackRequest) *ProjectsInstancesDatabasesSessionsRollbackCall {
	c := &ProjectsInstancesDatabasesSessionsRollbackCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.rollbackrequest = rollbackrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsRollbackCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsRollbackCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsRollbackCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsRollbackCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsRollbackCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsRollbackCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.rollbackrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:rollback")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.rollback", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.rollback" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesDatabasesSessionsRollbackCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.rollback", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesDatabasesSessionsStreamingReadCall struct {
	s           *Service
	session     string
	readrequest *ReadRequest
	urlParams_  gensupport.URLParams
	ctx_        context.Context
	header_     http.Header
}

// StreamingRead: Like Read, except returns the result set as a stream. Unlike
// Read, there is no limit on the size of the returned result set. However, no
// individual row in the result set can exceed 100 MiB, and no column value can
// exceed 10 MiB.
//
// - session: The session in which the read should be performed.
func (r *ProjectsInstancesDatabasesSessionsService) StreamingRead(session string, readrequest *ReadRequest) *ProjectsInstancesDatabasesSessionsStreamingReadCall {
	c := &ProjectsInstancesDatabasesSessionsStreamingReadCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.session = session
	c.readrequest = readrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesDatabasesSessionsStreamingReadCall) Fields(s ...googleapi.Field) *ProjectsInstancesDatabasesSessionsStreamingReadCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesDatabasesSessionsStreamingReadCall) Context(ctx context.Context) *ProjectsInstancesDatabasesSessionsStreamingReadCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesDatabasesSessionsStreamingReadCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesDatabasesSessionsStreamingReadCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.readrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+session}:streamingRead")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"session": c.session,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.streamingRead", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.databases.sessions.streamingRead" call.
// Any non-2xx status code is an error. Response headers are in either
// *PartialResultSet.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesDatabasesSessionsStreamingReadCall) Do(opts ...googleapi.CallOption) (*PartialResultSet, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &PartialResultSet{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.databases.sessions.streamingRead", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionOperationsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists instance partition long-running operations in the given
// instance. An instance partition operation has a name of the form
// `projects//instances//instancePartitions//operations/`. The long-running
// operation metadata field type `metadata.type_url` describes the type of the
// metadata. Operations returned include those that have
// completed/failed/canceled within the last 7 days, and pending operations.
// Operations returned are ordered by `operation.metadata.value.start_time` in
// descending order starting from the most recently started operation.
// Authorization requires `spanner.instancePartitionOperations.list` permission
// on the resource parent.
//
//   - parent: The parent instance of the instance partition operations. Values
//     are of the form `projects//instances/`.
func (r *ProjectsInstancesInstancePartitionOperationsService) List(parent string) *ProjectsInstancesInstancePartitionOperationsListCall {
	c := &ProjectsInstancesInstancePartitionOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": An expression that filters the
// list of returned operations. A filter expression consists of a field name, a
// comparison operator, and a value for filtering. The value must be a string,
// a number, or a boolean. The comparison operator must be one of: `<`, `>`,
// `<=`, `>=`, `!=`, `=`, or `:`. Colon `:` is the contains operator. Filter
// rules are not case sensitive. The following fields in the Operation are
// eligible for filtering: * `name` - The name of the long-running operation *
// `done` - False if the operation is in progress, else true. *
// `metadata.@type` - the type of metadata. For example, the type string for
// CreateInstancePartitionMetadata is
// `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstancePartition
// Metadata`. * `metadata.` - any field in metadata.value. `metadata.@type`
// must be specified first, if filtering on metadata fields. * `error` - Error
// associated with the long-running operation. * `response.@type` - the type of
// response. * `response.` - any field in response.value. You can combine
// multiple expressions by enclosing each expression in parentheses. By
// default, expressions are combined with AND logic. However, you can specify
// AND, OR, and NOT logic explicitly. Here are a few examples: * `done:true` -
// The operation is complete. * `(metadata.@type=` \
// `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstancePartition
// Metadata) AND` \
// `(metadata.instance_partition.name:custom-instance-partition) AND` \
// `(metadata.start_time < \"2021-03-28T14:50:00Z\") AND` \ `(error:*)` -
// Return operations where: * The operation's metadata type is
// CreateInstancePartitionMetadata. * The instance partition name contains
// "custom-instance-partition". * The operation started before
// 2021-03-28T14:50:00Z. * The operation resulted in an error.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) Filter(filter string) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// InstancePartitionDeadline sets the optional parameter
// "instancePartitionDeadline": Deadline used while retrieving metadata for
// instance partition operations. Instance partitions whose operation metadata
// cannot be retrieved within this deadline will be added to
// unreachable_instance_partitions in ListInstancePartitionOperationsResponse.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) InstancePartitionDeadline(instancePartitionDeadline string) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.urlParams_.Set("instancePartitionDeadline", instancePartitionDeadline)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of operations to be
// returned in the response. If 0 or less, defaults to the server's maximum
// allowed page size.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListInstancePartitionOperationsResponse to the same `parent` and with the
// same `filter`.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) PageToken(pageToken string) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instancePartitionOperations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitionOperations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitionOperations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListInstancePartitionOperationsResponse.ServerResponse.Header or (if a
// response was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) Do(opts ...googleapi.CallOption) (*ListInstancePartitionOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListInstancePartitionOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitionOperations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesInstancePartitionOperationsListCall) Pages(ctx context.Context, f func(*ListInstancePartitionOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesInstancePartitionsCreateCall struct {
	s                              *Service
	parent                         string
	createinstancepartitionrequest *CreateInstancePartitionRequest
	urlParams_                     gensupport.URLParams
	ctx_                           context.Context
	header_                        http.Header
}

// Create: Creates an instance partition and begins preparing it to be used.
// The returned long-running operation can be used to track the progress of
// preparing the new instance partition. The instance partition name is
// assigned by the caller. If the named instance partition already exists,
// `CreateInstancePartition` returns `ALREADY_EXISTS`. Immediately upon
// completion of this request: * The instance partition is readable via the
// API, with all requested attributes but no allocated resources. Its state is
// `CREATING`. Until completion of the returned operation: * Cancelling the
// operation renders the instance partition immediately unreadable via the API.
// * The instance partition can be deleted. * All other attempts to modify the
// instance partition are rejected. Upon completion of the returned operation:
// * Billing for all successfully-allocated resources begins (some types may
// have lower than the requested levels). * Databases can start using this
// instance partition. * The instance partition's allocated resource levels are
// readable via the API. * The instance partition's state becomes `READY`. The
// returned long-running operation will have a name of the format
// `/operations/` and can be used to track creation of the instance partition.
// The metadata field type is CreateInstancePartitionMetadata. The response
// field type is InstancePartition, if successful.
//
//   - parent: The name of the instance in which to create the instance
//     partition. Values are of the form `projects//instances/`.
func (r *ProjectsInstancesInstancePartitionsService) Create(parent string, createinstancepartitionrequest *CreateInstancePartitionRequest) *ProjectsInstancesInstancePartitionsCreateCall {
	c := &ProjectsInstancesInstancePartitionsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.createinstancepartitionrequest = createinstancepartitionrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsCreateCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsCreateCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.createinstancepartitionrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instancePartitions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.create", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.create" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsCreateCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.create", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes an existing instance partition. Requires that the instance
// partition is not used by any database or backup and is not the default
// instance partition of an instance. Authorization requires
// `spanner.instancePartitions.delete` permission on the resource name.
//
//   - name: The name of the instance partition to be deleted. Values are of the
//     form
//     `projects/{project}/instances/{instance}/instancePartitions/{instance_parti
//     tion}`.
func (r *ProjectsInstancesInstancePartitionsService) Delete(name string) *ProjectsInstancesInstancePartitionsDeleteCall {
	c := &ProjectsInstancesInstancePartitionsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Etag sets the optional parameter "etag": If not empty, the API only deletes
// the instance partition when the etag provided matches the current status of
// the requested instance partition. Otherwise, deletes the instance partition
// without checking the current status of the requested instance partition.
func (c *ProjectsInstancesInstancePartitionsDeleteCall) Etag(etag string) *ProjectsInstancesInstancePartitionsDeleteCall {
	c.urlParams_.Set("etag", etag)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsDeleteCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets information about a particular instance partition.
//
//   - name: The name of the requested instance partition. Values are of the form
//     `projects/{project}/instances/{instance}/instancePartitions/{instance_parti
//     tion}`.
func (r *ProjectsInstancesInstancePartitionsService) Get(name string) *ProjectsInstancesInstancePartitionsGetCall {
	c := &ProjectsInstancesInstancePartitionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesInstancePartitionsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesInstancePartitionsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsGetCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *InstancePartition.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesInstancePartitionsGetCall) Do(opts ...googleapi.CallOption) (*InstancePartition, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &InstancePartition{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists all instance partitions for the given instance.
//
//   - parent: The instance whose instance partitions should be listed. Values
//     are of the form `projects//instances/`. Use `{instance} = '-'` to list
//     instance partitions for all Instances in a project, e.g.,
//     `projects/myproject/instances/-`.
func (r *ProjectsInstancesInstancePartitionsService) List(parent string) *ProjectsInstancesInstancePartitionsListCall {
	c := &ProjectsInstancesInstancePartitionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// InstancePartitionDeadline sets the optional parameter
// "instancePartitionDeadline": Deadline used while retrieving metadata for
// instance partitions. Instance partitions whose metadata cannot be retrieved
// within this deadline will be added to unreachable in
// ListInstancePartitionsResponse.
func (c *ProjectsInstancesInstancePartitionsListCall) InstancePartitionDeadline(instancePartitionDeadline string) *ProjectsInstancesInstancePartitionsListCall {
	c.urlParams_.Set("instancePartitionDeadline", instancePartitionDeadline)
	return c
}

// PageSize sets the optional parameter "pageSize": Number of instance
// partitions to be returned in the response. If 0 or less, defaults to the
// server's maximum allowed page size.
func (c *ProjectsInstancesInstancePartitionsListCall) PageSize(pageSize int64) *ProjectsInstancesInstancePartitionsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": If non-empty,
// `page_token` should contain a next_page_token from a previous
// ListInstancePartitionsResponse.
func (c *ProjectsInstancesInstancePartitionsListCall) PageToken(pageToken string) *ProjectsInstancesInstancePartitionsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesInstancePartitionsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesInstancePartitionsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsListCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/instancePartitions")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListInstancePartitionsResponse.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsListCall) Do(opts ...googleapi.CallOption) (*ListInstancePartitionsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListInstancePartitionsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesInstancePartitionsListCall) Pages(ctx context.Context, f func(*ListInstancePartitionsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesInstancePartitionsPatchCall struct {
	s                              *Service
	nameid                         string
	updateinstancepartitionrequest *UpdateInstancePartitionRequest
	urlParams_                     gensupport.URLParams
	ctx_                           context.Context
	header_                        http.Header
}

// Patch: Updates an instance partition, and begins allocating or releasing
// resources as requested. The returned long-running operation can be used to
// track the progress of updating the instance partition. If the named instance
// partition does not exist, returns `NOT_FOUND`. Immediately upon completion
// of this request: * For resource types for which a decrease in the instance
// partition's allocation has been requested, billing is based on the
// newly-requested level. Until completion of the returned operation: *
// Cancelling the operation sets its metadata's cancel_time, and begins
// restoring resources to their pre-request values. The operation is guaranteed
// to succeed at undoing all resource changes, after which point it terminates
// with a `CANCELLED` status. * All other attempts to modify the instance
// partition are rejected. * Reading the instance partition via the API
// continues to give the pre-request resource levels. Upon completion of the
// returned operation: * Billing begins for all successfully-allocated
// resources (some types may have lower than the requested levels). * All
// newly-reserved resources are available for serving the instance partition's
// tables. * The instance partition's new resource levels are readable via the
// API. The returned long-running operation will have a name of the format
// `/operations/` and can be used to track the instance partition modification.
// The metadata field type is UpdateInstancePartitionMetadata. The response
// field type is InstancePartition, if successful. Authorization requires
// `spanner.instancePartitions.update` permission on the resource name.
//
//   - name: A unique identifier for the instance partition. Values are of the
//     form `projects//instances//instancePartitions/a-z*[a-z0-9]`. The final
//     segment of the name must be between 2 and 64 characters in length. An
//     instance partition's name cannot be changed after the instance partition
//     is created.
func (r *ProjectsInstancesInstancePartitionsService) Patch(nameid string, updateinstancepartitionrequest *UpdateInstancePartitionRequest) *ProjectsInstancesInstancePartitionsPatchCall {
	c := &ProjectsInstancesInstancePartitionsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.nameid = nameid
	c.updateinstancepartitionrequest = updateinstancepartitionrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsPatchCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsPatchCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_)
	body, err := googleapi.WithoutDataWrapper.JSONBuffer(c.updateinstancepartitionrequest)
	if err != nil {
		return nil, err
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.nameid,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.patch", "request", internallog.HTTPRequest(req, body.Bytes()))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.patch" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsPatchCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.patch", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsOperationsCancelCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Cancel: Starts asynchronous cancellation on a long-running operation. The
// server makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation, the
// operation is not deleted; instead, it becomes an operation with an
// Operation.error value with a google.rpc.Status.code of `1`, corresponding to
// `Code.CANCELLED`.
//
// - name: The name of the operation resource to be cancelled.
func (r *ProjectsInstancesInstancePartitionsOperationsService) Cancel(name string) *ProjectsInstancesInstancePartitionsOperationsCancelCall {
	c := &ProjectsInstancesInstancePartitionsOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsOperationsCancelCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsOperationsCancelCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsOperationsCancelCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsOperationsCancelCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsOperationsCancelCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.cancel", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.operations.cancel" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsOperationsCancelCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.cancel", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsOperationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a long-running operation. This method indicates that the
// client is no longer interested in the operation result. It does not cancel
// the operation. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`.
//
// - name: The name of the operation resource to be deleted.
func (r *ProjectsInstancesInstancePartitionsOperationsService) Delete(name string) *ProjectsInstancesInstancePartitionsOperationsDeleteCall {
	c := &ProjectsInstancesInstancePartitionsOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsOperationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsOperationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsOperationsDeleteCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsOperationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsOperationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsOperationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.operations.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsOperationsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
// service.
//
// - name: The name of the operation resource.
func (r *ProjectsInstancesInstancePartitionsOperationsService) Get(name string) *ProjectsInstancesInstancePartitionsOperationsGetCall {
	c := &ProjectsInstancesInstancePartitionsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesInstancePartitionsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesInstancePartitionsOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsOperationsGetCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.operations.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesInstancePartitionsOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesInstancePartitionsOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the request. If
// the server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// - name: The name of the operation's parent resource.
func (r *ProjectsInstancesInstancePartitionsOperationsService) List(name string) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c := &ProjectsInstancesInstancePartitionsOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list filter.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) Filter(filter string) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list page
// size.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list page
// token.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) PageToken(pageToken string) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// ReturnPartialSuccess sets the optional parameter "returnPartialSuccess":
// When set to `true`, operations that are reachable are returned as normal,
// and those that are unreachable are returned in the
// ListOperationsResponse.unreachable field. This can only be `true` when
// reading across collections. For example, when `parent` is set to
// "projects/example/locations/-". This field is not supported by default and
// will result in an `UNIMPLEMENTED` error if set unless explicitly documented
// otherwise in service or product specific documentation.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) ReturnPartialSuccess(returnPartialSuccess bool) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.urlParams_.Set("returnPartialSuccess", fmt.Sprint(returnPartialSuccess))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) Context(ctx context.Context) *ProjectsInstancesInstancePartitionsOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesInstancePartitionsOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.instancePartitions.operations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOperationsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.instancePartitions.operations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesInstancePartitionsOperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ProjectsInstancesOperationsCancelCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Cancel: Starts asynchronous cancellation on a long-running operation. The
// server makes a best effort to cancel the operation, but success is not
// guaranteed. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or
// other methods to check whether the cancellation succeeded or whether the
// operation completed despite cancellation. On successful cancellation, the
// operation is not deleted; instead, it becomes an operation with an
// Operation.error value with a google.rpc.Status.code of `1`, corresponding to
// `Code.CANCELLED`.
//
// - name: The name of the operation resource to be cancelled.
func (r *ProjectsInstancesOperationsService) Cancel(name string) *ProjectsInstancesOperationsCancelCall {
	c := &ProjectsInstancesOperationsCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesOperationsCancelCall) Fields(s ...googleapi.Field) *ProjectsInstancesOperationsCancelCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesOperationsCancelCall) Context(ctx context.Context) *ProjectsInstancesOperationsCancelCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesOperationsCancelCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesOperationsCancelCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:cancel")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.cancel", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.operations.cancel" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesOperationsCancelCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.cancel", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesOperationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a long-running operation. This method indicates that the
// client is no longer interested in the operation result. It does not cancel
// the operation. If the server doesn't support this method, it returns
// `google.rpc.Code.UNIMPLEMENTED`.
//
// - name: The name of the operation resource to be deleted.
func (r *ProjectsInstancesOperationsService) Delete(name string) *ProjectsInstancesOperationsDeleteCall {
	c := &ProjectsInstancesOperationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesOperationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsInstancesOperationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesOperationsDeleteCall) Context(ctx context.Context) *ProjectsInstancesOperationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesOperationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesOperationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.delete", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.operations.delete" call.
// Any non-2xx status code is an error. Response headers are in either
// *Empty.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesOperationsDeleteCall) Do(opts ...googleapi.CallOption) (*Empty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Empty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.delete", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation. Clients can use this
// method to poll the operation result at intervals as recommended by the API
// service.
//
// - name: The name of the operation resource.
func (r *ProjectsInstancesOperationsService) Get(name string) *ProjectsInstancesOperationsGetCall {
	c := &ProjectsInstancesOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsInstancesOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsInstancesOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesOperationsGetCall) Context(ctx context.Context) *ProjectsInstancesOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.get", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.operations.get" call.
// Any non-2xx status code is an error. Response headers are in either
// *Operation.ServerResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was returned.
func (c *ProjectsInstancesOperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &Operation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.get", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

type ProjectsInstancesOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the request. If
// the server doesn't support this method, it returns `UNIMPLEMENTED`.
//
// - name: The name of the operation's parent resource.
func (r *ProjectsInstancesOperationsService) List(name string) *ProjectsInstancesOperationsListCall {
	c := &ProjectsInstancesOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list filter.
func (c *ProjectsInstancesOperationsListCall) Filter(filter string) *ProjectsInstancesOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list page
// size.
func (c *ProjectsInstancesOperationsListCall) PageSize(pageSize int64) *ProjectsInstancesOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list page
// token.
func (c *ProjectsInstancesOperationsListCall) PageToken(pageToken string) *ProjectsInstancesOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// ReturnPartialSuccess sets the optional parameter "returnPartialSuccess":
// When set to `true`, operations that are reachable are returned as normal,
// and those that are unreachable are returned in the
// ListOperationsResponse.unreachable field. This can only be `true` when
// reading across collections. For example, when `parent` is set to
// "projects/example/locations/-". This field is not supported by default and
// will result in an `UNIMPLEMENTED` error if set unless explicitly documented
// otherwise in service or product specific documentation.
func (c *ProjectsInstancesOperationsListCall) ReturnPartialSuccess(returnPartialSuccess bool) *ProjectsInstancesOperationsListCall {
	c.urlParams_.Set("returnPartialSuccess", fmt.Sprint(returnPartialSuccess))
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ProjectsInstancesOperationsListCall) Fields(s ...googleapi.Field) *ProjectsInstancesOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ProjectsInstancesOperationsListCall) IfNoneMatch(entityTag string) *ProjectsInstancesOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ProjectsInstancesOperationsListCall) Context(ctx context.Context) *ProjectsInstancesOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ProjectsInstancesOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsInstancesOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.projects.instances.operations.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListOperationsResponse.ServerResponse.Header or (if a response was returned
// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsInstancesOperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.projects.instances.operations.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsInstancesOperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

type ScansListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Return available scans given a Database-specific resource name.
//
//   - parent: The unique name of the parent resource, specific to the Database
//     service implementing this interface.
func (r *ScansService) List(parent string) *ScansListCall {
	c := &ScansListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": A filter expression to restrict
// the results based on information present in the available Scan collection.
// The filter applies to all fields within the Scan message except for `data`.
func (c *ScansListCall) Filter(filter string) *ScansListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The maximum number of items
// to return.
func (c *ScansListCall) PageSize(pageSize int64) *ScansListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The next_page_token value
// returned from a previous List request, if any.
func (c *ScansListCall) PageToken(pageToken string) *ScansListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// View sets the optional parameter "view": Specifies which parts of the Scan
// should be returned in the response. Note, only the SUMMARY view (the
// default) is currently supported for ListScans.
//
// Possible values:
//
//	"VIEW_UNSPECIFIED" - Not specified, equivalent to SUMMARY.
//	"SUMMARY" - Server responses only include `name`, `details`, `start_time`
//
// and `end_time`. The default value. Note, the ListScans method may only use
// this view type, others view types are not supported.
//
//	"FULL" - Full representation of the scan is returned in the server
//
// response, including `data`.
func (c *ScansListCall) View(view string) *ScansListCall {
	c.urlParams_.Set("view", view)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more
// details.
func (c *ScansListCall) Fields(s ...googleapi.Field) *ScansListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets an optional parameter which makes the operation fail if the
// object's ETag matches the given value. This is useful for getting updates
// only after the object has changed since the last request.
func (c *ScansListCall) IfNoneMatch(entityTag string) *ScansListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method.
func (c *ScansListCall) Context(ctx context.Context) *ScansListCall {
	c.ctx_ = ctx
	return c
}

// Header returns a http.Header that can be modified by the caller to add
// headers to the request.
func (c *ScansListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ScansListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_)
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, nil)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	c.s.logger.DebugContext(c.ctx_, "api request", "serviceName", apiName, "rpcName", "spanner.scans.list", "request", internallog.HTTPRequest(req, nil))
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "spanner.scans.list" call.
// Any non-2xx status code is an error. Response headers are in either
// *ListScansResponse.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified was
// returned.
func (c *ScansListCall) Do(opts ...googleapi.CallOption) (*ListScansResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, gensupport.WrapError(&googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		})
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, gensupport.WrapError(err)
	}
	ret := &ListScansResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	b, err := gensupport.DecodeResponseBytes(target, res)
	if err != nil {
		return nil, err
	}
	c.s.logger.DebugContext(c.ctx_, "api response", "serviceName", apiName, "rpcName", "spanner.scans.list", "response", internallog.HTTPResponse(res, b))
	return ret, nil
}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ScansListCall) Pages(ctx context.Context, f func(*ListScansResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken"))
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}
