Copyright 2019 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Package postgres provides functionality for reading and writing to the postgres database.
package postgres

import (
	
	
	

	
	
	
	
)

type DB struct {
	db                 *database.DB
	bypassLicenseCheck bool
	expoller           *poller.Poller
	cancel             func()
}
New returns a new postgres DB.
func ( *database.DB) *DB {
	return newdb(, false)
}
NewBypassingLicenseCheck returns a new postgres DB that bypasses license checks. That means all data will be inserted and returned for non-redistributable modules, packages and directories.
func ( *database.DB) *DB {
	return newdb(, true)
}
For testing.
var startPoller = true

func ( *database.DB,  bool) *DB {
	 := poller.New(
		[]string(nil),
		func( context.Context) (interface{}, error) {
			return getExcludedPrefixes(, )
		},
		func( error) {
			log.Errorf(context.Background(), "getting excluded prefixes: %v", )
		})
	,  := context.WithCancel(context.Background())
	if startPoller {
		.Poll() // Initialize the state.
		.Start(, time.Minute)
	}
	return &DB{
		db:                 ,
		bypassLicenseCheck: ,
		expoller:           ,
		cancel:             ,
	}
}
Close closes a DB.
func ( *DB) () error {
	.cancel()
	return .db.Close()
}
Underlying returns the *database.DB inside db.
func ( *DB) () *database.DB {
	return .db
}
StalenessTimestamp returns the index timestamp of the oldest module that is newer than the index timestamp of the youngest module we have processed. That is, let T be the maximum index timestamp of all processed modules. Then this function return the minimum index timestamp of unprocessed modules that is no less than T, or an error that wraps derrors.NotFound if there is none. The name of the function is imprecise: there may be an older unprocessed module, if one newer than it has been processed. We use this function to compute a metric that is a lower bound on the time it takes to process a module since it appeared in the index.
func ( *DB) ( context.Context) (time.Time, error) {
	var  time.Time
	 := .db.QueryRow(, `
		SELECT m.index_timestamp
		FROM module_version_states m
		CROSS JOIN (
			-- the index timestamp of the youngest processed module
			SELECT index_timestamp
			FROM module_version_states
			WHERE last_processed_at IS NOT NULL
			ORDER BY 1 DESC
			LIMIT 1
		) yp
		WHERE m.index_timestamp > yp.index_timestamp
		AND last_processed_at IS NULL
		ORDER BY m.index_timestamp ASC
		LIMIT 1
	`).Scan(&)
	switch  {
	case nil:
		return , nil
	case sql.ErrNoRows:
		return time.Time{}, derrors.NotFound
	default:
		return time.Time{}, 
	}
}
collectStrings runs the query, which must select for a single string column, and returns a slice of the resulting strings.
func ( context.Context,  *database.DB,  string,  ...interface{}) ( []string,  error) {
	defer derrors.WrapStack(&, "DB.collectStrings(%q)", )

	 = .RunQuery(, , func( *sql.Rows) error {
		var  string
		if  := .Scan(&);  != nil {
			return 
		}
		 = append(, )
		return nil
	}, ...)
	if  != nil {
		return nil, 
	}
	return , nil