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: device.go
    path of file: ./repos/convoy/database/postgres
    
    the code of the file until where you have to start completion: package postgres

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"github.com/frain-dev/convoy/cache"

	"github.com/frain-dev/convoy/database"
	"github.com/frain-dev/convoy/datastore"
	"github.com/jmoiron/sqlx"
)

var (
	ErrDeviceNotCreated = errors.New("device could not be created")
	ErrDeviceNotFound   = errors.New("device not found")
	ErrDeviceNotUpdated = errors.New("device could not be updated")
	ErrDeviceNotDeleted = errors.New("device could not be deleted")
)

const (
	createDevice = `
	INSERT INTO convoy.devices (id, project_id, host_name, status, last_seen_at)
	VALUES ($1, $2, $3, $4, $5)
	`

	updateDevice = `
	UPDATE convoy.devices SET
	host_name = $3
    
func (d *deviceRepo) LoadDevicesPaged(ctx context.Context, projectID string, filter *datastore.ApiKeyFilter, pageable datastore.Pageable) ([]datastore.Device, datastore.PaginationData, error) {
	var query, filterQuery string
	var args []interface{}
	var err error

	arg := map[string]interface{}{
		"project_id": projectID,
		"limit":      pageable.Limit(),
		"cursor":     pageable.Cursor(),
	}

	if pageable.Direction == datastore.Next {
		query = baseFetchDevicesPagedForward
	} else {
		query = baseFetchDevicesPagedBackward
	}

	filterQuery = baseDevicesFilter

	query = fmt.Sprintf(query, fetchDevicesPaginated, filterQuery)

	query, args, err = sqlx.Named(query, arg)
	if err != nil {
		return nil, datastore.PaginationData{}, err
	}

	query, args, err = sqlx.In(query, args...)
	if err != nil {
		return nil, datastore.PaginationData{}, err
	}

	query = d.db.Rebind(query)

	rows, err := d.db.QueryxContext(ctx, query, args...)
	if err != nil {
		return nil, datastore.PaginationData{}, err
	}
	defer closeWithError(rows)

	var devices []datastore.Device
	for rows.Next() {
		var data DevicePaginated

		err = rows.StructScan(&data)
		if err != nil {
			return nil, datastore.PaginationData{}, err
		}

		devices = append(devices, data.Device)
	}

	var count datastore.PrevRowCount
	if len(devices) > 0 {
		var countQuery string
		var qargs []interface{}
		first := devices[0]
		qarg := arg
		qarg["cursor"] = first.UID

		cq := fmt.Sprintf(countPrevDevices, filterQuery)
		countQuery, qargs, err = sqlx.Named(cq, qarg)
		if err != nil {
			return nil, datastore.PaginationData{}, err
		}

		countQuery = d.db.Rebind(countQuery)

		// count the row number before the first row
		rows, err := d.db.QueryxContext(ctx, countQuery, qargs...)
		if err != nil {
			return nil, datastore.PaginationData{}, err
		}
		defer closeWithError(rows)

		if rows.Next() {
			err = rows.StructScan(&count)
			if err != nil {
				return nil, datastore.PaginationData{}, err
			}
		}
	}

	ids := make([]string, len(devices))
	for i := range devices {
		ids[i] = devices[i].UID
	}

	if len(devices) > pageable.PerPage {
		devices = devices[:len(devices)-1]
	}

	pagination := &datastore.PaginationData{PrevRowCount: count}
	pagination = pagination.Build(pageable, ids)

	return devices, *pagination, nil
}