You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: metadata.go
    path of file: ./repos/usql/drivers/metadata/informationschema
    
    the code of the file until where you have to start completion: // Package informationschema provides metadata readers that query tables from
// the information_schema schema. It tries to be database agnostic,
// but there is a set of options to configure what tables and columns to expect.
package informationschema

import (
	"database/sql"
	"fmt"
	"strings"

	"github.com/xo/usql/drivers"
	"github.com/xo/usql/drivers/metadata"
	"github.com/xo/usql/text"
)

// InformationSchema metadata reader
type InformationSchema struct {
	metadata.LoggingReader
	pf                  func(int) string
	hasFunctions        bool
	hasSequences        bool
	hasIndexes          bool
	hasConstraints      bool
	hasCheckConstraints bool
	hasTablePrivileges  bool
	hasColumnPrivileges bool
	hasUsagePrivileges  bool
	clauses             map[ClauseName]string
	limit               int
	systemSchemas       []string
	currentSchema       string
	dataTypeFormatter   func(metadata.Column) string
}

var _ metadata.BasicReader = &InformationSchema{}

type Logger interface {
	Println(...interface{})
}

type ClauseName string

const (
	ColumnsDataType         = ClauseName("columns.data_type")
	ColumnsColumnSize       = ClauseName("columns.column_size")
	ColumnsNumericScale     = ClauseName("columns.numeric_scale")
	ColumnsNumericPrecRadix = ClauseName("columns.numeric_precision_radix")
	ColumnsCharOctetLength  = ClauseName("columns.character_octet_length")

	FunctionColumnsColumnSize       = ClauseName("function_columns.column_size")
	FunctionColumnsNumericScale     = ClauseName("function_columns.numeric_scale")
	FunctionColumnsNumericPrecRadix = ClauseName("function_columns.numeric_precision_radix")
	FunctionColumnsCharOctetLength  = ClauseName("function_columns.character_octet_length")

	FunctionsSecurityType = ClauseName("functions.security_type")

	ConstraintIsDeferrable      = ClauseName("constrain
    
func (s InformationSchema) ConstraintColumns(f metadata.Filter) (*metadata.ConstraintColumnSet, error) {
	if !s.hasConstraints {
		return nil, text.ErrNotSupported
	}

	vals := []interface{}{}
	qstr := ""
	if s.hasCheckConstraints {
		qstr = `SELECT
	  c.constraint_catalog,
	  c.table_schema,
	  c.table_name,
	  c.constraint_name,
	  c.column_name,
	  1 AS ordinal_position,
	  '' AS foreign_catalog,
	  '' AS foreign_schema,
	  '' AS foreign_table,
	  '' AS foreign_name
	FROM information_schema.constraint_column_usage c
	`
		conds, checkVals := s.conditions(len(vals)+1, f, formats{
			catalog:    "c.constraint_catalog LIKE %s",
			schema:     "c.table_schema LIKE %s",
			notSchemas: "c.table_schema NOT IN (%s)",
			parent:     "c.table_name LIKE %s",
			name:       "c.constraint_name LIKE %s",
		})
		if len(conds) != 0 {
			qstr += " WHERE " + strings.Join(conds, " AND ")
			vals = append(vals, checkVals...)
		}
		qstr += `
UNION ALL
`
	}
	qstr += `SELECT
  c.constraint_catalog,
  c.table_schema,
  c.table_name,
  c.constraint_name,
  c.column_name,
  c.ordinal_position,
  COALESCE(f.constraint_catalog, '') AS foreign_catalog,
  COALESCE(f.table_schema, '') AS foreign_schema,
  COALESCE(f.table_name, '') AS foreign_table,
  COALESCE(f.column_name, '') AS foreign_name
FROM information_schema.key_column_usage c
LEFT JOIN information_schema.referential_constraints r ON c.constraint_catalog = r.constraint_catalog
  AND c.constraint_schema = r.constraint_schema
  AND c.constraint_name = r.constraint_name
LEFT JOIN information_schema.key_column_usage f ON r.unique_constraint_catalog = f.constraint_catalog
  AND r.unique_constraint_schema = f.constraint_schema
  AND r.unique_constraint_name = f.constraint_name
  ` + s.clauses[ConstraintJoinCond] + `
  AND c.position_in_unique_constraint = f.ordinal_position
`
	conds, keyVals := s.conditions(len(vals)+1, f, formats{
		catalog:    "c.constraint_catalog LIKE %s",
		schema:     "c.table_schema LIKE %s",
		notSchemas: "c.table_schema NOT IN (%s)",
		parent:     "c.table_name LIKE %s",
		reference:  "f.table_name LIKE %s",
		name:       "c.constraint_name LIKE %s",
	})
	if len(conds) != 0 {
		qstr += " WHERE " + strings.Join(conds, " AND ")
		vals = append(vals, keyVals...)
	}
	rows, closeRows, err := s.query(qstr, []string{}, "constraint_catalog, table_schema, table_name, constraint_name, ordinal_position, column_name", vals...)
	if err != nil {
		if err == sql.ErrNoRows {
			return metadata.NewConstraintColumnSet([]metadata.ConstraintColumn{}), nil
		}
		return nil, err
	}
	defer closeRows()

	results := []metadata.ConstraintColumn{}
	i := 1
	for rows.Next() {
		rec := metadata.ConstraintColumn{OrdinalPosition: i}
		i++
		err = rows.Scan(
			&rec.Catalog,
			&rec.Schema,
			&rec.Table,
			&rec.Constraint,
			&rec.Name,
			&rec.OrdinalPosition,
			&rec.ForeignCatalog,
			&rec.ForeignSchema,
			&rec.ForeignTable,
			&rec.ForeignName,
		)
		if err != nil {
			return nil, err
		}
		results = append(results, rec)
	}
	if rows.Err() != nil {
		return nil, rows.Err()
	}
	return metadata.NewConstraintColumnSet(results), nil
}