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: encoder.go
    path of file: ./repos/portmaster/netquery/orm
    
    the code of the file until where you have to start completion: package orm

import (
	"context"
	"fmt"
	"reflect"
	"time"

	"golang.org/x/exp/slices"
	"zombiezen.com/go/sqlite"
)

type (
	// EncodeFunc is called for each non-basic type during encoding.
	EncodeFunc func(col *ColumnDef, valType reflect.Type, val reflect.Value) (interface{}, bool, error)

	// EncodeConfig holds encoding functions.
	EncodeConfig struct {
		EncodeHooks []EncodeFunc
	}
)

// ToParamMap returns a map that contains the sqlite compatible 
    
func ToParamMap(ctx context.Context, r interface{}, keyPrefix string, cfg EncodeConfig, skipFields []string) (map[string]interface{}, error) {
	// make sure we work on a struct type
	val := reflect.Indirect(reflect.ValueOf(r))
	if val.Kind() != reflect.Struct {
		return nil, fmt.Errorf("%w, got %T", errStructExpected, r)
	}

	res := make(map[string]interface{}, val.NumField())

	for i := 0; i < val.NumField(); i++ {
		fieldType := val.Type().Field(i)
		field := val.Field(i)

		// skip unexported fields
		if !fieldType.IsExported() {
			continue
		}

		colDef, err := getColumnDef(fieldType)
		if err != nil {
			return nil, fmt.Errorf("failed to get column definition for %s: %w", fieldType.Name, err)
		}

		if slices.Contains(skipFields, colDef.Name) {
			continue
		}

		x, found, err := runEncodeHooks(
			colDef,
			fieldType.Type,
			field,
			append(
				cfg.EncodeHooks,
				encodeBasic(),
			),
		)
		if err != nil {
			return nil, fmt.Errorf("failed to run encode hooks: %w", err)
		}

		if !found {
			if reflect.Indirect(field).IsValid() {
				x = reflect.Indirect(field).Interface()
			}
		}

		res[keyPrefix+sqlColumnName(fieldType)] = x

	}

	return res, nil
}