func SelectDataAll(conn *sqlite.Conn, order string, page, limit uint) (
	[]fat1.NFTokenID, []factom.FAAddress, []factom.Bytes32, [][]byte, error) {
	if page == 0 {
		return nil, nil, nil, nil, fmt.Errorf("invalid page")
	}
	stmt := conn.Prep(`SELECT "id", "owner", "creation_hash", "metadata"
                        FROM "nftoken_address";`)
	defer stmt.Reset()
	var tkns []fat1.NFTokenID
	var owners []factom.FAAddress
	var creationHashes []factom.Bytes32
	var metadata [][]byte
	for {
		hasRow, err := stmt.Step()
		if err != nil {
			return nil, nil, nil, nil, err
		}
		if !hasRow {
			break
		}
		tkns = append(tkns, fat1.NFTokenID(stmt.ColumnInt64(0)))
		var owner factom.FAAddress
		if stmt.ColumnBytes(1, owner[:]) != len(owner) {
			panic("invalid address length")
		}
		owners = append(owners, owner)
		var creationHash factom.Bytes32
		if stmt.ColumnBytes(2, creationHash[:]) != len(creationHash) {
			panic("invalid hash length")
		}
		creationHashes = append(creationHashes, creationHash)
		data := make([]byte, stmt.ColumnLen(3))
		stmt.ColumnBytes(3, data)
		metadata = append(metadata, data)
	}
	return tkns, owners, creationHashes, metadata, nil
}
SelectDataAll returns the nfIDs, owner addresses, creation entry hashes, and
the NFToken metadata for the given pagination range of NFTokens.

Pages start at 1.
package nftoken
import (
	"encoding/json"
	"fmt"
	"crawshaw.io/sqlite"
	"crawshaw.io/sqlite/sqlitex"
	"github.com/AdamSLevy/sqlbuilder"
	"github.com/Factom-Asset-Tokens/factom"
	"github.com/Factom-Asset-Tokens/factom/fat1"
)
const CreateTable = `CREATE TABLE "nftoken" (
        "id"                      INTEGER PRIMARY KEY,
        "metadata"                BLOB,
        "creation_entry_id"       INTEGER NOT NULL,
        "owner_id"                INTEGER NOT NULL,
        FOREIGN KEY("creation_entry_id") REFERENCES "entry",
        FOREIGN KEY("owner_id") REFERENCES "address"
);
CREATE INDEX "idx_nftoken_metadata" ON nftoken("metadata");
CREATE INDEX "idx_nftoken_owner_id" ON nftoken("owner_id");
CREATE VIEW "nftoken_address" AS
        SELECT "nftoken"."id" AS "id",
                "metadata",
                "hash" AS "creation_hash",
                "address" AS "owner" FROM
                        "nftoken", "address", "entry" ON
                                "owner_id" = "address"."id" AND
                                "creation_entry_id" = "entry"."id";
`
func Insert(conn *sqlite.Conn, nfID fat1.NFTokenID, adrID, entryID int64) (error, error) {
	stmt := conn.Prep(`INSERT INTO "nftoken"
                ("id", "owner_id", "creation_entry_id") VALUES (?, ?, ?);`)
	stmt.BindInt64(1, int64(nfID))
	stmt.BindInt64(2, adrID)
	stmt.BindInt64(3, entryID)
	if _, err := stmt.Step(); err != nil {
		if sqlite.ErrCode(err) == sqlite.SQLITE_CONSTRAINT_PRIMARYKEY {
			return fmt.Errorf("NFTokenID{%v} already exists", nfID), nil
		}
		return nil, err
	}
	return nil, nil
}
func SetOwner(conn *sqlite.Conn, nfID fat1.NFTokenID, adrID int64) error {
	stmt := conn.Prep(`UPDATE "nftoken" SET "owner_id" = ? WHERE "id" = ?;`)
	stmt.BindInt64(1, adrID)
	stmt.BindInt64(2, int64(nfID))
	_, err := stmt.Step()
	if conn.Changes() == 0 {
		panic("no NFTokenID updated")
	}
	return err
}
func SetMetadata(conn *sqlite.Conn, nfID fat1.NFTokenID, metadata json.RawMessage) error {
	stmt := conn.Prep(`UPDATE "nftoken" SET "metadata" = ? WHERE "id" = ?;`)
	stmt.BindBytes(1, metadata)
	stmt.BindInt64(2, int64(nfID))
	_, err := stmt.Step()
	if conn.Changes() == 0 {
		panic("no NFTokenID updated")
	}
	return err
}
func SelectOwnerID(conn *sqlite.Conn, nfID fat1.NFTokenID) (int64, error) {
	stmt := conn.Prep(`SELECT "owner_id" FROM "nftoken" WHERE "id" = ?;`)
	stmt.BindInt64(1, int64(nfID))
	ownerID, err := sqlitex.ResultInt64(stmt)
	if err != nil && err.Error() == "sqlite: statement has no results" {
		return -1, nil
	}
	if err != nil {
		return -1, err
	}
	return ownerID, nil
}
func SelectData(conn *sqlite.Conn, nfID fat1.NFTokenID) (
	factom.FAAddress, factom.Bytes32, []byte, error) {
	var owner factom.FAAddress
	var creationHash factom.Bytes32
	stmt := conn.Prep(`SELECT "owner", "metadata", "creation_hash"
                        FROM "nftoken_address" WHERE "id" = ?;`)
	stmt.BindInt64(1, int64(nfID))
	hasRow, err := stmt.Step()
	defer stmt.Reset()
	if err != nil {
		return owner, creationHash, nil, err
	}
	if !hasRow {
		return owner, creationHash, nil, nil
	}
	if stmt.ColumnBytes(0, owner[:]) != len(owner) {
		panic("invalid address length")
	}
	metadata := make([]byte, stmt.ColumnLen(1))
	stmt.ColumnBytes(1, metadata)
	if stmt.ColumnBytes(2, creationHash[:]) != len(creationHash) {
		panic("invalid hash length")
	}
	return owner, creationHash, metadata, nil
}