internal

package
v8.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2022 License: ISC Imports: 2 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CreateAddressTable = `` /* 291-byte string literal not displayed */

	// InsertAddressRow inserts a address block row without checking for unique
	// index conflicts. This should only be used before the unique indexes are
	// created or there may be constraint violations (errors).
	InsertAddressRow = insertAddressRow + `RETURNING id;`

	// UpsertAddressRow is an upsert (insert or update on conflict), returning
	// the inserted/updated address row id.
	UpsertAddressRow = insertAddressRow + `ON CONFLICT (tx_vin_vout_row_id, address, is_funding) DO UPDATE
		SET matching_tx_hash = $2, tx_hash = $3, tx_vin_vout_index = $4,
		block_time = $7, valid_mainchain = $9 RETURNING id;`

	// InsertAddressRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with addresses' unique tx index, while returning the row id of
	// either the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertAddressRowOnConflictDoNothing = `WITH inserting AS (` +
		insertAddressRow +
		`	ON CONFLICT (tx_vin_vout_row_id, address, is_funding) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM inserting
		UNION  ALL
		SELECT id FROM addresses
		WHERE  address = $1 AND is_funding = $8 AND tx_vin_vout_row_id = $5 -- only executed if no INSERT
		LIMIT  1;`

	// IndexAddressTableOnVoutID creates the unique index uix_addresses_vout_id
	// on (tx_vin_vout_row_id, address, is_funding).
	IndexAddressTableOnVoutID = `CREATE UNIQUE INDEX IF NOT EXISTS ` + IndexOfAddressTableOnVoutID +
		` ON addresses(tx_vin_vout_row_id, address, is_funding);`
	DeindexAddressTableOnVoutID = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnVoutID + ` CASCADE;`

	// IndexBlockTimeOnTableAddress creates a sorted index on block_time, which
	// accelerates queries with ORDER BY block_time LIMIT n OFFSET m.
	IndexBlockTimeOnTableAddress = `CREATE INDEX IF NOT EXISTS ` + IndexOfAddressTableOnBlockTime +
		` ON addresses(block_time DESC NULLS LAST);`
	DeindexBlockTimeOnTableAddress = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnBlockTime + ` CASCADE;`

	IndexAddressTableOnMatchingTxHash = `CREATE INDEX IF NOT EXISTS ` + IndexOfAddressTableOnMatchingTx +
		` ON addresses(matching_tx_hash);`
	DeindexAddressTableOnMatchingTxHash = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnMatchingTx + ` CASCADE;`

	IndexAddressTableOnAddress = `CREATE INDEX IF NOT EXISTS ` + IndexOfAddressTableOnAddress +
		` ON addresses(address);`
	DeindexAddressTableOnAddress = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnAddress + ` CASCADE;`

	IndexAddressTableOnTxHash = `CREATE INDEX IF NOT EXISTS ` + IndexOfAddressTableOnTx +
		` ON addresses(tx_hash);`
	DeindexAddressTableOnTxHash = `DROP INDEX IF EXISTS ` + IndexOfAddressTableOnTx + ` CASCADE;`

	SelectAddressAllByAddress = `SELECT ` + addrsColumnNames + ` FROM addresses
		WHERE address=$1
		ORDER BY block_time DESC, tx_hash ASC;`
	SelectAddressAllMainchainByAddress = `SELECT ` + addrsColumnNames + ` FROM addresses
		WHERE address=$1 AND valid_mainchain
		ORDER BY block_time DESC, tx_hash ASC;`

	SelectAddressesAllTxnWithHeight = `` /* 294-byte string literal not displayed */

	SelectAddressesAllTxn = `` /* 130-byte string literal not displayed */

	SelectAddressUnspentCountANDValue = `` /* 142-byte string literal not displayed */

	SelectAddressSpentCountANDValue = `` /* 141-byte string literal not displayed */

	SelectAddressesMergedSpentCount = `SELECT COUNT( DISTINCT tx_hash ) FROM addresses
		WHERE address = $1 AND is_funding = FALSE AND valid_mainchain = TRUE;`

	SelectAddressesMergedFundingCount = `SELECT COUNT( DISTINCT tx_hash ) FROM addresses
		WHERE address = $1 AND is_funding = TRUE AND valid_mainchain = TRUE;`

	SelectAddressesMergedCount = `SELECT COUNT( DISTINCT tx_hash ) FROM addresses
		WHERE address = $1 AND valid_mainchain = TRUE;`

	// SelectAddressSpentUnspentCountAndValue gets the number and combined spent
	// and unspent outpoints for the given address. The key is the "GROUP BY
	// is_funding, matching_tx_hash=”" part of the statement that gets the data
	// for the combinations of is_funding (boolean) and matching_tx_hash=”
	// (boolean). There should never be any with is_funding=true where
	// matching_tx_hash is empty, thus there are three rows in the output. For
	// example, the first row is the spending transactions that must have
	// matching_tx_hash set, the second row the the funding transactions for the
	// first row (notice the equal count and sum), and the third row are the
	// unspent outpoints that are is_funding=true but with an empty
	// matching_tx_hash:
	//
	// count  |      sum       | is_funding | all_empty_matching | no_empty_matching
	// --------+----------------+------------+--------------------+--------------------
	//   45150 | 12352318108368 | f          | f                  | t
	//   45150 | 12352318108368 | t          | f                  | t
	//  229145 | 55875634749104 | t          | t                  | f
	// (3 rows)
	//
	// Since part of the grouping is on "matching_tx_hash = ”", what is
	// logically "any" empty matching is actually no_empty_matching.
	SelectAddressSpentUnspentCountAndValue = `` /* 393-byte string literal not displayed */

	SelectAddressUnspentWithTxn = `` /* 463-byte string literal not displayed */

	SelectAddressLimitNByAddress = `SELECT ` + addrsColumnNames + ` FROM addresses
		WHERE address=$1 AND valid_mainchain = TRUE
		ORDER BY block_time DESC, tx_hash ASC
		LIMIT $2 OFFSET $3;`

	SelectAddressMergedDebitView = `` /* 317-byte string literal not displayed */

	SelectAddressMergedCreditView = `` /* 316-byte string literal not displayed */

	SelectAddressMergedViewAll = `` /* 412-byte string literal not displayed */

	SelectAddressMergedView = SelectAddressMergedViewAll + ` LIMIT $2 OFFSET $3;`

	SelectAddressCsvView = "SELECT tx_hash, valid_mainchain, matching_tx_hash, value, block_time, is_funding, " +
		"tx_vin_vout_index, tx_type FROM addresses WHERE address=$1 ORDER BY block_time DESC"

	SelectAddressDebitsLimitNByAddress = `SELECT ` + addrsColumnNames + `
		FROM addresses WHERE address=$1 AND is_funding = FALSE AND valid_mainchain
		ORDER BY block_time DESC, tx_hash ASC
		LIMIT $2 OFFSET $3;`

	SelectAddressCreditsLimitNByAddress = `SELECT ` + addrsColumnNames + `
		FROM addresses WHERE address=$1 AND is_funding AND valid_mainchain
		ORDER BY block_time DESC, tx_hash ASC
		LIMIT $2 OFFSET $3;`

	SelectAddressIDsByFundingOutpoint = `` /* 129-byte string literal not displayed */

	SelectAddressIDByVoutIDAddress = `SELECT id FROM addresses WHERE address=$1 AND
	    tx_vin_vout_row_id=$2 AND is_funding;`

	SelectAddressOldestTxBlockTime = `SELECT block_time FROM addresses WHERE
		address=$1 ORDER BY block_time LIMIT 1;`

	UpdateAllAddressesMatchingTxHashRange = `` /* 312-byte string literal not displayed */

	UpdateAllAddressesMatchingTxHash = `` /* 267-byte string literal not displayed */

	UpdateAllAddressesMatchingTxHash1 = `` /* 361-byte string literal not displayed */

	UpdateAllAddressesMatchingTxHash2 = `` /* 391-byte string literal not displayed */

	// SetAddressMatchingTxHashForOutpoint sets the matching tx hash (a spending
	// transaction) for the addresses rows corresponding to the specified
	// outpoint (tx_hash:tx_vin_vout_index), a funding tx row.
	SetAddressMatchingTxHashForOutpoint = `UPDATE addresses SET matching_tx_hash=$1
		WHERE tx_hash=$2 AND is_funding AND tx_vin_vout_index=$3 AND valid_mainchain = $4 `  // not terminated with ;

	// AssignMatchingTxHashForOutpoint is like
	// SetAddressMatchingTxHashForOutpoint except that it only updates rows
	// where matching_tx_hash is not already set.
	AssignMatchingTxHashForOutpoint = SetAddressMatchingTxHashForOutpoint + ` AND matching_tx_hash='';`

	SetAddressMainchainForVoutIDs = `UPDATE addresses SET valid_mainchain=$1
		WHERE is_funding = TRUE AND tx_vin_vout_row_id=$2;`

	SetAddressMainchainForVinIDs = `UPDATE addresses SET valid_mainchain=$1
		WHERE is_funding = FALSE AND tx_vin_vout_row_id=$2;`

	SetTxTypeOnAddressesByVinAndVoutIDs = `UPDATE addresses SET tx_type=$1 WHERE
		tx_vin_vout_row_id=$2 AND is_funding=$3;`

	// SelectAddressesGloballyInvalid selects the row ids of the addresses table
	// corresponding to transactions that should have valid_mainchain set to
	// false according to the transactions table. Should is defined as any
	// occurrence of a given transaction (hash) being flagged as is_valid AND
	// is_mainchain.
	SelectAddressesGloballyInvalid = `` /* 403-byte string literal not displayed */

	// UpdateAddressesGloballyInvalid sets valid_mainchain=false on address rows
	// identified by the SelectAddressesGloballyInvalid query (ids of
	// globally_invalid subquery table) as requiring this flag set, but which do
	// not already have it set (incorrectly_valid).
	UpdateAddressesGloballyInvalid = `UPDATE addresses SET valid_mainchain=false
		FROM (
			SELECT id FROM
			(
				` + SelectAddressesGloballyInvalid + `
			) AS invalid_ids
			WHERE invalid_ids.valid_mainchain=true
		) AS incorrectly_valid
		WHERE incorrectly_valid.id=addresses.id;`

	// UpdateAddressesFundingMatchingHash sets matching_tx_hash as per the vins
	// table. This is needed to fix partially updated addresses table entries
	// that were affected by stake invalidation.
	UpdateAddressesFundingMatchingHash = `` /* 276-byte string literal not displayed */

	// UpdateValidMainchainFromTransactions sets valid_mainchain in all rows of
	// the addresses table according to the transactions table, unlike
	// UpdateAddressesGloballyInvalid that does it selectively for only the
	// incorrectly set addresses table rows.  This is much slower.
	UpdateValidMainchainFromTransactions = `` /* 157-byte string literal not displayed */

)

These queries relate primarily to the "addresses" table.

View Source
const (
	CreateBlockTable = `` /* 546-byte string literal not displayed */

	// InsertBlockRow inserts a new block row without checking for unique index
	// conflicts. This should only be used before the unique indexes are created
	// or there may be constraint violations (errors).
	InsertBlockRow = insertBlockRow + `RETURNING id;`

	// UpsertBlockRow is an upsert (insert or update on conflict), returning
	// the inserted/updated block row id.
	UpsertBlockRow = insertBlockRow + `ON CONFLICT (hash) DO UPDATE
		SET is_valid = $4, is_mainchain = $5 RETURNING id;`

	// InsertBlockRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with blocks' unique tx index, while returning the row id of
	// either the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertBlockRowOnConflictDoNothing = `WITH ins AS (` +
		insertBlockRow +
		`	ON CONFLICT (hash) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM ins
		UNION  ALL
		SELECT id FROM blocks
		WHERE  hash = $1 -- only executed if no INSERT
		LIMIT  1;`

	// IndexBlockTableOnHash creates the unique index uix_block_hash on (hash).
	IndexBlockTableOnHash   = `CREATE UNIQUE INDEX ` + IndexOfBlocksTableOnHash + ` ON blocks(hash);`
	DeindexBlockTableOnHash = `DROP INDEX ` + IndexOfBlocksTableOnHash + ` CASCADE;`

	// IndexBlocksTableOnHeight creates the index uix_block_height on (height).
	// This is not unique because of side chains.
	IndexBlocksTableOnHeight   = `CREATE INDEX ` + IndexOfBlocksTableOnHeight + ` ON blocks(height);`
	DeindexBlocksTableOnHeight = `DROP INDEX ` + IndexOfBlocksTableOnHeight + ` CASCADE;`

	// IndexBlocksTableOnHeight creates the index uix_block_time on (time).
	// This is not unique because of side chains.
	IndexBlocksTableOnTime   = `CREATE INDEX ` + IndexOfBlocksTableOnTime + ` ON blocks("time");`
	DeindexBlocksTableOnTime = `DROP INDEX ` + IndexOfBlocksTableOnTime + ` CASCADE;`

	SelectBlockByTimeRangeSQL = `SELECT hash, height, size, time, numtx
		FROM blocks WHERE time BETWEEN $1 and $2 ORDER BY time DESC LIMIT $3;`
	SelectBlockByTimeRangeSQLNoLimit = `SELECT hash, height, size, time, numtx
		FROM blocks WHERE time BETWEEN $1 and $2 ORDER BY time DESC;`
	SelectBlockHashByHeight = `SELECT hash FROM blocks WHERE height = $1 AND is_mainchain = true;`
	SelectBlockHeightByHash = `SELECT height FROM blocks WHERE hash = $1;`

	SelectBlockTimeByHeight = `SELECT time FROM blocks
		WHERE height = $1 AND is_mainchain = true;`

	RetrieveBestBlockHeightAny = `SELECT id, hash, height FROM blocks
		ORDER BY height DESC LIMIT 1;`
	RetrieveBestBlockHeight = `SELECT id, hash, height FROM blocks
		WHERE is_mainchain = true ORDER BY height DESC LIMIT 1;`

	// SelectBlocksTicketsPrice selects the ticket price and difficulty for the
	// first block in a stake difficulty window.
	SelectBlocksTicketsPrice = `SELECT sbits, time, difficulty, height, fresh_stake
		FROM blocks
		WHERE height > $1
		ORDER BY height;`

	SelectGenesisTime = `SELECT time
		FROM blocks
		WHERE height = 0
		AND is_mainchain`

	SelectWindowsByLimit = `` /* 397-byte string literal not displayed */

	SelectBlocksTimeListingByLimit = `` /* 377-byte string literal not displayed */

	SelectBlocksPreviousHash = `SELECT previous_hash FROM blocks WHERE hash = $1;`

	SelectBlocksHashes = `SELECT hash FROM blocks ORDER BY id;`

	SelectBlockVoteCount = `SELECT voters FROM blocks WHERE hash = $1;`

	SelectSideChainBlocks = `` /* 171-byte string literal not displayed */

	SelectSideChainTips = `` /* 177-byte string literal not displayed */

	SelectBlockStatus = `` /* 151-byte string literal not displayed */

	SelectBlockFlags = `SELECT is_valid, is_mainchain
		FROM blocks
		WHERE hash = $1;`

	SelectDisapprovedBlocks = `` /* 171-byte string literal not displayed */

	SelectTxsPerDay = `SELECT date_trunc('day',time) AS date, sum(numtx)
		FROM blocks
		WHERE time > $1
		GROUP BY date
		ORDER BY date;`

	UpdateLastBlockValid = `UPDATE blocks SET is_valid = $2 WHERE id = $1;`
	UpdateBlockMainchain = `UPDATE blocks SET is_mainchain = $2 WHERE hash = $1 RETURNING previous_hash;`

	// CreateBlockPrevNextTable creates a new table named block_chain. The
	// primary key is not a SERIAL, but rather the row ID of the block in the
	// blocks table.
	CreateBlockPrevNextTable = `` /* 164-byte string literal not displayed */

	// InsertBlockPrevNext includes the primary key, which should be the row ID
	// of the corresponding block in the blocks table.
	InsertBlockPrevNext = `` /* 134-byte string literal not displayed */

	SelectBlockChainRowIDByHash = `SELECT block_db_id FROM block_chain WHERE this_hash = $1;`

	UpdateBlockNext           = `UPDATE block_chain SET next_hash = $2 WHERE block_db_id = $1;`
	UpdateBlockNextByHash     = `UPDATE block_chain SET next_hash = $2 WHERE this_hash = $1;`
	UpdateBlockNextByNextHash = `UPDATE block_chain SET next_hash = $2 WHERE next_hash = $1;`

	SelectBlockStats = `SELECT height, size, time, chainwork, numtx
		FROM blocks
		WHERE is_mainchain
		AND height > $1
		ORDER BY height;`

	// Get the height data. Because stats is unique on height, the inner join will
	// filter for mainchain as well.
	SelectBlockDataByHeight = `` /* 257-byte string literal not displayed */

	SelectBlockDataRange = `` /* 295-byte string literal not displayed */

	SelectBlockDataRangeDesc = `` /* 300-byte string literal not displayed */

	SelectBlockDataRangeWithSkip = `` /* 327-byte string literal not displayed */

	SelectBlockDataRangeWithSkipDesc = `` /* 332-byte string literal not displayed */

	SelectBlockDataByHash = `` /* 281-byte string literal not displayed */

	SelectBlockDataBest = `` /* 289-byte string literal not displayed */

	SelectBlockSizeByHeight = `SELECT size
		FROM blocks
		WHERE is_mainchain AND height = $1;`

	SelectBlockSizeRange = `SELECT size
		FROM blocks
		WHERE is_mainchain
			AND height BETWEEN $1 AND $2;`

	SelectSBitsByHeight = `SELECT sbits
		FROM blocks
		WHERE height = $1 AND is_mainchain;`

	SelectSBitsByHash = `SELECT sbits
		FROM blocks
		WHERE hash = $1;`

	SelectSBitsRange = `SELECT sbits
		FROM blocks
		WHERE height BETWEEN $1 AND $2;`

	SelectDiffByTime = `SELECT difficulty
		FROM blocks
		WHERE time >= $1
		ORDER BY time
		LIMIT 1;`
)

These queries relate primarily to the "blocks" and "block_chain" tables.

View Source
const (
	// IndexExists checks if an index with a given name in certain namespace
	// (schema) exists.
	IndexExists = `SELECT 1
		FROM   pg_class c
		JOIN   pg_namespace n ON n.oid = c.relnamespace
		WHERE  c.relname = $1 AND n.nspname = $2;`

	// IndexIsUnique checks if an index with a given name in certain namespace
	// (schema) exists, and is a UNIQUE index.
	IndexIsUnique = `` /* 175-byte string literal not displayed */

	// CreateTestingTable creates the testing table.
	CreateTestingTable = `CREATE TABLE IF NOT EXISTS testing (
		id SERIAL8 PRIMARY KEY,
		timestamp TIMESTAMP,
		timestamptz TIMESTAMPTZ
	);`
)
View Source
const (
	IndexOfBlocksTableOnHash   = "uix_block_hash"
	IndexOfBlocksTableOnHeight = "uix_block_height"
	IndexOfBlocksTableOnTime   = "uix_block_time"

	IndexOfTransactionsTableOnHashes      = "uix_tx_hashes"
	IndexOfTransactionsTableOnBlockInd    = "uix_tx_block_in"
	IndexOfTransactionsTableOnBlockHeight = "ix_tx_block_height"

	IndexOfVinsTableOnVin     = "uix_vin"
	IndexOfVinsTableOnPrevOut = "uix_vin_prevout"

	IndexOfVoutsTableOnTxHashInd = "uix_vout_txhash_ind"
	IndexOfVoutsTableOnSpendTxID = "uix_vout_spendtxid_ind"

	IndexOfAddressTableOnAddress    = "uix_addresses_address"
	IndexOfAddressTableOnVoutID     = "uix_addresses_vout_id"
	IndexOfAddressTableOnBlockTime  = "block_time_index"
	IndexOfAddressTableOnTx         = "uix_addresses_funding_tx"
	IndexOfAddressTableOnMatchingTx = "matching_tx_hash_index"

	IndexOfTicketsTableOnHashes     = "uix_ticket_hashes_index"
	IndexOfTicketsTableOnTxRowID    = "uix_ticket_ticket_db_id"
	IndexOfTicketsTableOnPoolStatus = "uix_tickets_pool_status"

	IndexOfVotesTableOnHashes    = "uix_votes_hashes_index"
	IndexOfVotesTableOnBlockHash = "uix_votes_block_hash"
	IndexOfVotesTableOnCandBlock = "uix_votes_candidate_block"
	IndexOfVotesTableOnVersion   = "uix_votes_vote_version"
	IndexOfVotesTableOnHeight    = "uix_votes_height"
	IndexOfVotesTableOnBlockTime = "uix_votes_block_time"

	IndexOfMissesTableOnHashes = "uix_misses_hashes_index"

	IndexOfAgendasTableOnName = "uix_agendas_name"

	IndexOfAgendaVotesTableOnRowIDs = "uix_agenda_votes"

	IndexOfProposalsTableOnToken = "uix_proposals"

	IndexOfProposalVotesTableOnProposalsID = "uix_proposal_votes"

	IndexOfHeightOnStatsTable = "uix_stats_height"
)

The names of table column indexes are defined in this block.

View Source
const (
	CreateMetaTable = `` /* 241-byte string literal not displayed */

	InsertMetaRow = `` /* 200-byte string literal not displayed */

	SelectMetaDBVersions = `SELECT
		compatibility_version,
		schema_version,
		maintenance_version
	FROM meta;`

	SelectMetaDBBestBlock = `SELECT
		best_block_height,
		best_block_hash
	FROM meta;`

	SetMetaDBBestBlock = `UPDATE meta
		SET best_block_height = $1, best_block_hash = $2;`

	SelectMetaDBIbdComplete = `SELECT ibd_complete FROM meta;`

	SetMetaDBIbdComplete = `UPDATE meta
		SET ibd_complete = $1;`

	SetDBSchemaVersion = `UPDATE meta
		SET schema_version = $1;`

	SetDBMaintenanceVersion = `UPDATE meta
		SET maintenance_version = $1;`
)

These queries relate primarily to the "meta" table.

View Source
const (

	// DeleteAddresses deletes rows of the addresses table (funding and
	// spending) corresponding to all of the transactions (regular and stake)
	// for a given block.
	DeleteAddresses = `` /* 358-byte string literal not displayed */

	DeleteAddressesSubQry = `DELETE FROM addresses WHERE id IN (` + addressesForBlockHash + `);`

	DeleteStakeAddressesFunding = `` /* 217-byte string literal not displayed */

	DeleteStakeAddressesSpending = `` /* 214-byte string literal not displayed */

	DeleteVins = `` /* 185-byte string literal not displayed */

	DeleteVinsSubQry = `DELETE FROM vins WHERE id IN (` + vinsForBlockHash + `);`

	// DeleteStakeVins deletes rows of the vins table corresponding to inputs of
	// the stake transactions (transactions.vin_db_ids) for a block
	// (blocks.stxdbids) specified by its hash (blocks.hash).
	DeleteStakeVins = `` /* 159-byte string literal not displayed */

	// DeleteStakeVinsSubSelect is like DeleteStakeVins except it is implemented
	// using sub-queries rather than a join.
	DeleteStakeVinsSubSelect = `` /* 173-byte string literal not displayed */

	// DeleteRegularVins deletes rows of the vins table corresponding to inputs
	// of the regular/non-stake transactions (transactions.vin_db_ids) for a
	// block (blocks.txdbids) specified by its hash (blocks.hash).
	DeleteRegularVins = `` /* 158-byte string literal not displayed */

	// DeleteRegularVinsSubSelect is like DeleteRegularVins except it is
	// implemented using sub-queries rather than a join.
	DeleteRegularVinsSubSelect = `` /* 172-byte string literal not displayed */

	DeleteVouts = `` /* 188-byte string literal not displayed */

	DeleteVoutsSubQry = `DELETE FROM vouts WHERE id IN (` + voutsForBlockHash + `);`

	// DeleteStakeVouts deletes rows of the vouts table corresponding to inputs
	// of the stake transactions (transactions.vout_db_ids) for a block
	// (blocks.stxdbids) specified by its hash (blocks.hash).
	DeleteStakeVouts = `` /* 162-byte string literal not displayed */

	// DeleteStakeVoutsSubSelect is like DeleteStakeVouts except it is
	// implemented using sub-queries rather than a join.
	DeleteStakeVoutsSubSelect = `` /* 175-byte string literal not displayed */

	// DeleteRegularVouts deletes rows of the vouts table corresponding to
	// inputs of the regular/non-stake transactions (transactions.vout_db_ids)
	// for a block (blocks.txdbids) specified by its hash (blocks.hash).
	DeleteRegularVouts = `` /* 161-byte string literal not displayed */

	// DeleteRegularVoutsSubSelect is like DeleteRegularVouts except it is
	// implemented using sub-queries rather than a join.
	DeleteRegularVoutsSubSelect = `` /* 174-byte string literal not displayed */

	DeleteMisses = `DELETE FROM misses
		WHERE block_hash=$1;`

	DeleteVotes = `DELETE FROM votes
		WHERE block_hash=$1;`

	DeleteTickets = `DELETE FROM tickets
		USING blocks
		WHERE purchase_tx_db_id = ANY(blocks.stxdbids)
			AND blocks.hash=$1;`
	DeleteTicketsSimple = `DELETE FROM tickets
		WHERE block_hash=$1;`

	DeleteTransactions = `` /* 135-byte string literal not displayed */

	DeleteTransactionsSimple = `DELETE FROM transactions
		WHERE block_hash=$1
		RETURNING id;`

	DeleteBlock = `DELETE FROM blocks
		WHERE hash=$1;`

	DeleteBlockFromChain = `DELETE FROM block_chain
		WHERE this_hash=$1
		RETURNING prev_hash;`

	ClearBlockChainNextHash = `UPDATE block_chain
		SET next_hash=''
		WHERE next_hash=$1;`
)

These queries relate to the blockchain "rewind" operations involving multiple tables.

View Source
const (
	// UnmatchedSpending lists addresses with no matching_tx_hash set but with
	// is_funding=FALSE. Spending address rows should always have a matching
	// transaction hash.
	UnmatchedSpending = `SELECT id, address
		FROM addresses
		WHERE char_length(matching_tx_hash)=0
			AND NOT is_funding;`

	// ExtraMainchainBlocks lists mainchain blocks at heights where there are
	// more than one mainchain block (impossible).
	ExtraMainchainBlocks = `` /* 319-byte string literal not displayed */

	// MislabeledInvalidBlocks lists blocks labeled as approved, but for which
	// the following block has specified vote bits that invalidate it.
	MislabeledInvalidBlocks = `` /* 218-byte string literal not displayed */

	// MainchainBlocksWithSidechainParent lists side chain blocks that are the
	// parent of a main chain block (impossible).
	MainchainBlocksWithSidechainParent = `` /* 290-byte string literal not displayed */

	// UnspentTicketsWithSpendInfo lists tickets that are flagged as unspent,
	// but which have set either spend_height or spend_tx_db_id.
	UnspentTicketsWithSpendInfo = `` /* 144-byte string literal not displayed */

	// SpentTicketsWithoutSpendInfo lists tickets that are flagged as spent, but
	// which do not have set either spend_height or spend_tx_db_id.
	SpentTicketsWithoutSpendInfo = `` /* 137-byte string literal not displayed */

	// MislabeledTicketTransactions lists transactions in the transactions table
	// that also appear in the tickets table, but which do not have the proper
	// tx_type (1) set.
	MislabeledTicketTransactions = `` /* 158-byte string literal not displayed */

	// MissingTickets lists ticket transactions in the transactions table (with
	// tx_type=1) that do NOT appear in the tickets table.
	MissingTickets = `` /* 185-byte string literal not displayed */

	// MissingTicketTransactions lists tickets in the tickets table that do not
	// appear in the transactions table at all.
	MissingTicketTransactions = `` /* 156-byte string literal not displayed */

	// TicketPoolStatuses lists all combinations of pool_status (live, voted,
	// expired, missed) and spend_type (unspent, voted, revoked).
	//
	//  pool_status | spend_type |  count
	// -------------+------------+---------
	//            0 |          0 |   42388 <- live
	//            1 |          2 | 1675471 <- voted
	//            2 |          0 |      57 <- expired, unspent
	//            2 |          1 |   11346 <- expired, revoked
	//            3 |          0 |    1137 <- missed, unspent
	//            3 |          1 |   25837 <- missed, revoked
	// (6 rows)
	TicketPoolStatuses = `` /* 126-byte string literal not displayed */

	// BadSpentLiveTickets lists tickets with live pool_status, but not unspent
	// spend_type. There should be none.
	BadSpentLiveTickets = `SELECT id, tx_hash, spend_type
		FROM tickets
		WHERE pool_status=0 AND spend_type!=0;`

	// BadVotedTickets lists tickets with voted pool_status, but not voted
	// spend_type. Voted tickets should not be live, expired, or missed.
	BadVotedTickets = `SELECT id, tx_hash, spend_type
		FROM tickets
		WHERE pool_status=1 AND spend_type!=2;`

	// BadExpiredVotedTickets lists tickets with expired pool_status, but with
	// voted spend_type. Expired tickets should only be unspent or revoked.
	BadExpiredVotedTickets = `SELECT id, tx_hash, spend_type
		FROM tickets
		WHERE pool_status=2 AND spend_type=2;`

	// BadMissedVotedTickets lists tickets with missed pool_status, but with
	// voted spend_type. Missed tickets should only be unspent or revoked.
	BadMissedVotedTickets = `SELECT id, tx_hash, spend_type
		FROM tickets
		WHERE pool_status=3 AND spend_type=2;`

	// DisapprovedBlockVotes lists the number of votes approving and
	// disapproving the blocks that are flagged as not valid (disapproved).
	//
	//                           candidate_hash                          | approvals | disapprovals | total
	// ------------------------------------------------------------------+-----------+--------------+-------
	//  000000000000031e720866f4bd3d4135c5473adc78d3bed22b816dafd55c6dc4 |         2 |            2 |     4
	//  00000000000003f1df8d2ec247864ecc250e53fa4a84e5e9d04b868aae15d4bd |         2 |            2 |     4
	//  00000000000003ae4fa13a6dcd53bf2fddacfac12e86e5b5f98a08a71d3e6caa |         2 |            2 |     4
	//  00000000000008ba8f3d37d27cd45e31906c1cbf45e0de3999fac06ef29b429b |         2 |            3 |     5
	//  0000000000000b5355c8bfb606cd40350e11739d53fb2fc191562c1d6d05b153 |         2 |            2 |     4
	//  0000000000000d7410d10b15b6ec0741cee77682c5e1e9263ca13fd749c47cad |         2 |            3 |     5
	//  000000000000124769cb7f199bcd5543b897374b6e1f6f8866a22ab425e15009 |         2 |            2 |     4
	//  0000000000000eaaa27b96df1228ffc96bcb7e0e476f9180d7d40f886c446e82 |         2 |            2 |     4
	//  000000000000075097acfdf8a3da309919712ebcff28a9e12dd3d9df787565a1 |         2 |            3 |     5
	// (9 rows)
	DisapprovedBlockVotes = `` /* 438-byte string literal not displayed */

	// BadBlockApproval lists blocks with an incorrect is_valid flag as
	// determined by computing (approvals/total_votes > 0.5).
	BadBlockApproval = `` /* 589-byte string literal not displayed */

)
View Source
const (
	CreateTicketsTable = `` /* 395-byte string literal not displayed */

	// InsertTicketRow inserts a new ticket row without checking for unique
	// index conflicts. This should only be used before the unique indexes are
	// created or there may be constraint violations (errors).
	InsertTicketRow = insertTicketRow + `RETURNING id;`

	// UpsertTicketRow is an upsert (insert or update on conflict), returning
	// the inserted/updated ticket row id. is_mainchain is updated as this might
	// be a reorganization.
	UpsertTicketRow = insertTicketRow + `ON CONFLICT (tx_hash, block_hash) DO UPDATE
		SET is_mainchain = $13 RETURNING id;`

	// InsertTicketRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with tickets' unique tx index, while returning the row id of
	// either the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertTicketRowOnConflictDoNothing = `WITH ins AS (` +
		insertTicketRow +
		`	ON CONFLICT (tx_hash, block_hash) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM ins
		UNION  ALL
		SELECT id FROM tickets
		WHERE  tx_hash = $1 AND block_hash = $2 -- only executed if no INSERT
		LIMIT  1;`

	// DeleteTicketsDuplicateRows removes rows that would violate the unique
	// index uix_ticket_hashes_index. This should be run prior to creating the
	// index.
	DeleteTicketsDuplicateRows = `` /* 185-byte string literal not displayed */

	// IndexTicketsTableOnHashes creates the unique index
	// uix_ticket_hashes_index on (tx_hash, block_hash).
	IndexTicketsTableOnHashes = `CREATE UNIQUE INDEX IF NOT EXISTS ` + IndexOfTicketsTableOnHashes +
		` ON tickets(tx_hash, block_hash);`
	DeindexTicketsTableOnHashes = `DROP INDEX IF EXISTS ` + IndexOfTicketsTableOnHashes + ` CASCADE;`

	// IndexTicketsTableOnTxDbID creates the unique index that ensures only one
	// row in the tickets table may refer to a certain row of the transactions
	// table. This is not the same as being unique on transaction hash, since
	// the transactions table also has a unique constraint is on (tx_hash,
	// block_hash) that allows a transaction appearing in multiple blocks (e.g.
	// side chains and/or invalidated blocks) to have multiple rows in the
	// transactions table.
	IndexTicketsTableOnTxDbID = `CREATE UNIQUE INDEX IF NOT EXISTS ` + IndexOfTicketsTableOnTxRowID +
		` ON tickets(purchase_tx_db_id);`
	DeindexTicketsTableOnTxDbID = `DROP INDEX IF EXISTS ` + IndexOfTicketsTableOnTxRowID + ` CASCADE;`

	IndexTicketsTableOnPoolStatus = `CREATE INDEX IF NOT EXISTS ` + IndexOfTicketsTableOnPoolStatus +
		` ON tickets(pool_status);`
	DeindexTicketsTableOnPoolStatus = `DROP INDEX IF EXISTS ` + IndexOfTicketsTableOnPoolStatus + ` CASCADE;`

	SelectTicketsInBlock        = `SELECT * FROM tickets WHERE block_hash = $1;`
	SelectTicketsTxDbIDsInBlock = `SELECT purchase_tx_db_id FROM tickets WHERE block_hash = $1;`
	SelectTicketsForAddress     = `SELECT * FROM tickets WHERE stakesubmission_address = $1;`

	SelectTicketIDHeightByHash = `SELECT id, block_height FROM tickets` + forTxHashMainchainFirst
	SelectTicketIDByHash       = `SELECT id FROM tickets` + forTxHashMainchainFirst
	SelectTicketStatusByHash   = `SELECT id, spend_type, pool_status FROM tickets` + forTxHashMainchainFirst
	SelectTicketInfoByHash     = `SELECT block_hash, block_height, spend_type, pool_status, spend_tx_db_id FROM tickets` + forTxHashMainchainFirst

	SelectUnspentTickets = `SELECT id, tx_hash FROM tickets
		WHERE spend_type = 0 AND is_mainchain = true;`

	SelectTicketsForPriceAtLeast = `SELECT * FROM tickets WHERE price >= $1;`
	SelectTicketsForPriceAtMost  = `SELECT * FROM tickets WHERE price <= $1;`

	SelectTicketsByPrice = `` /* 316-byte string literal not displayed */

	SelectTicketSpendTypeByBlock = `` /* 126-byte string literal not displayed */

	SetTicketSpendingInfoForHash = `` /* 136-byte string literal not displayed */

	SetTicketSpendingInfoForTicketDbID = `UPDATE tickets
		SET spend_type = $4, spend_height = $2, spend_tx_db_id = $3, pool_status = $5
		WHERE id = $1;`
	SetTicketSpendingInfoForTxDbID = `` /* 126-byte string literal not displayed */

	SetTicketPoolStatusForTicketDbID = `UPDATE tickets SET pool_status = $2 WHERE id = $1;`
	SetTicketPoolStatusForHash       = `UPDATE tickets SET pool_status = $2 WHERE tx_hash = $1;`

	UpdateTicketsMainchainAll = `` /* 136-byte string literal not displayed */

	UpdateTicketsMainchainByBlock = `UPDATE tickets
		SET is_mainchain=$1
		WHERE block_hash=$2;`

	// CreateVotesTable creates a new table named votes. block_time field is
	// needed to plot "Cumulative Vote Choices" agendas chart that plots
	// cumulative votes count against time over the voting period.
	CreateVotesTable = `` /* 364-byte string literal not displayed */

	// InsertVoteRow inserts a new vote row without checking for unique index
	// conflicts. This should only be used before the unique indexes are created
	// or there may be constraint violations (errors).
	InsertVoteRow = insertVoteRow + `RETURNING id;`

	// UpsertVoteRow is an upsert (insert or update on conflict), returning the
	// inserted/updated vote row id. is_mainchain is updated as this might be a
	// reorganization.
	UpsertVoteRow = insertVoteRow + `ON CONFLICT (tx_hash, block_hash) DO UPDATE
		SET is_mainchain = $12 RETURNING id;`

	// InsertVoteRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with votes' unique tx index, while returning the row id of
	// either the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertVoteRowOnConflictDoNothing = `WITH ins AS (` +
		insertVoteRow +
		`	ON CONFLICT (tx_hash, block_hash) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM ins
		UNION  ALL
		SELECT id FROM votes
		WHERE  tx_hash = $2 AND block_hash = $3 -- only executed if no INSERT
		LIMIT  1;`

	// DeleteVotesDuplicateRows removes rows that would violate the unique index
	// uix_votes_hashes_index. This should be run prior to creating the index.
	DeleteVotesDuplicateRows = `` /* 181-byte string literal not displayed */

	// IndexVotesTableOnHashes creates the unique index uix_votes_hashes_index
	// on (tx_hash, block_hash).
	IndexVotesTableOnHashes = `CREATE UNIQUE INDEX ` + IndexOfVotesTableOnHashes +
		` ON votes(tx_hash, block_hash);`
	DeindexVotesTableOnHashes = `DROP INDEX ` + IndexOfVotesTableOnHashes + ` CASCADE;`

	IndexVotesTableOnBlockHash = `CREATE INDEX ` + IndexOfVotesTableOnBlockHash +
		` ON votes(block_hash);`
	DeindexVotesTableOnBlockHash = `DROP INDEX ` + IndexOfVotesTableOnBlockHash + ` CASCADE;`

	IndexVotesTableOnCandidate = `CREATE INDEX ` + IndexOfVotesTableOnCandBlock +
		` ON votes(candidate_block_hash);`
	DeindexVotesTableOnCandidate = `DROP INDEX ` + IndexOfVotesTableOnCandBlock + ` CASCADE;`

	IndexVotesTableOnVoteVersion = `CREATE INDEX ` + IndexOfVotesTableOnVersion +
		` ON votes(version);`
	DeindexVotesTableOnVoteVersion = `DROP INDEX ` + IndexOfVotesTableOnVersion + ` CASCADE;`

	IndexVotesTableOnHeight = `CREATE INDEX ` + IndexOfVotesTableOnHeight + ` ON votes(height);`

	DeindexVotesTableOnHeight = `DROP INDEX ` + IndexOfVotesTableOnHeight + ` CASCADE;`

	IndexVotesTableOnBlockTime = `CREATE INDEX ` + IndexOfVotesTableOnBlockTime +
		` ON votes(block_time);`
	DeindexVotesTableOnBlockTime = `DROP INDEX ` + IndexOfVotesTableOnBlockTime + ` CASCADE;`

	SelectAllVoteDbIDsHeightsTicketHashes = `SELECT id, height, ticket_hash FROM votes;`
	SelectAllVoteDbIDsHeightsTicketDbIDs  = `SELECT id, height, ticket_tx_db_id FROM votes;`

	UpdateVotesMainchainAll = `` /* 134-byte string literal not displayed */

	UpdateVotesMainchainByBlock = `UPDATE votes
		SET is_mainchain=$1
		WHERE block_hash=$2;`

	CreateMissesTable = `` /* 173-byte string literal not displayed */

	// InsertMissRow inserts a new miss row without checking for unique index
	// conflicts. This should only be used before the unique indexes are created
	// or there may be constraint violations (errors).
	InsertMissRow = insertMissRow + `RETURNING id;`

	// UpsertMissRow is an upsert (insert or update on conflict), returning
	// the inserted/updated miss row id.
	UpsertMissRow = insertMissRow + `ON CONFLICT (ticket_hash, block_hash) DO UPDATE
		SET ticket_hash = $4, block_hash = $2 RETURNING id;`

	// InsertMissRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with misses' unique tx index, while returning the row id of
	// either the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertMissRowOnConflictDoNothing = `WITH ins AS (` +
		insertMissRow +
		`	ON CONFLICT (ticket_hash, block_hash) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM ins
		UNION  ALL
		SELECT id FROM misses
		WHERE  block_hash = $2 AND ticket_hash = $4 -- only executed if no INSERT
		LIMIT  1;`

	// DeleteMissesDuplicateRows removes rows that would violate the unique
	// index uix_misses_hashes_index. This should be run prior to creating the
	// index.
	DeleteMissesDuplicateRows = `` /* 187-byte string literal not displayed */

	// IndexMissesTableOnHashes creates the unique index uix_misses_hashes_index
	// on (ticket_hash, block_hash).
	IndexMissesTableOnHashes = `CREATE UNIQUE INDEX ` + IndexOfMissesTableOnHashes +
		` ON misses(ticket_hash, block_hash);`
	DeindexMissesTableOnHashes = `DROP INDEX ` + IndexOfMissesTableOnHashes + ` CASCADE;`

	SelectMissesInBlock = `SELECT ticket_hash FROM misses WHERE block_hash = $1;`

	SelectMissesForTicket = `SELECT height, block_hash FROM misses WHERE ticket_hash = $1;`

	SelectMissesMainchainForTicket = `` /* 160-byte string literal not displayed */

	SelectMissCountNonZeros = `` /* 200-byte string literal not displayed */

	SelectMissCountPerBlock = `` /* 294-byte string literal not displayed */

	CreateAgendasTable = `` /* 148-byte string literal not displayed */

	InsertAgendaRow = insertAgendaRow + `RETURNING id;`

	UpsertAgendaRow = insertAgendaRow + `ON CONFLICT (name) DO UPDATE
		SET status = $2, locked_in = $3, activated = $4, hard_forked = $5 RETURNING id;`

	IndexAgendasTableOnAgendaID = `CREATE UNIQUE INDEX ` + IndexOfAgendasTableOnName +
		` ON agendas(name);`
	DeindexAgendasTableOnAgendaID = `DROP INDEX ` + IndexOfAgendasTableOnName + ` CASCADE;`

	SelectAllAgendas = `SELECT id, name, status, locked_in, activated, hard_forked
		FROM agendas;`

	SelectAgendasLockedIn = `SELECT locked_in FROM agendas WHERE name = $1;`

	SelectAgendasHardForked = `SELECT hard_forked FROM agendas WHERE name = $1;`

	SelectAgendasActivated = `SELECT activated FROM agendas WHERE name = $1;`

	SetVoteMileStoneheights = `UPDATE agendas SET status = $2, locked_in = $3,
		activated = $4, hard_forked = $5 WHERE id = $1;`

	// DeleteAgendasDuplicateRows removes rows that would violate the unique
	// index uix_agendas_name. This should be run prior to creating the index.
	DeleteAgendasDuplicateRows = `` /* 170-byte string literal not displayed */

	CreateAgendaVotesTable = `` /* 140-byte string literal not displayed */

	InsertAgendaVotesRow = insertAgendaVotesRow + `RETURNING id;`

	UpsertAgendaVotesRow = insertAgendaVotesRow + `ON CONFLICT (agendas_row_id,
		votes_row_id) DO UPDATE SET agenda_vote_choice = $3 RETURNING id;`

	IndexAgendaVotesTableOnAgendaID = `CREATE UNIQUE INDEX ` + IndexOfAgendaVotesTableOnRowIDs +
		` ON agenda_votes(votes_row_id, agendas_row_id);`
	DeindexAgendaVotesTableOnAgendaID = `DROP INDEX ` + IndexOfAgendaVotesTableOnRowIDs + ` CASCADE;`

	// DeleteAgendaVotesDuplicateRows removes rows that would violate the unique
	// index uix_agenda_votes. This should be run prior to creating the index.
	DeleteAgendaVotesDuplicateRows = `` /* 204-byte string literal not displayed */

	SelectAgendasVotesByTime = `SELECT votes.block_time AS timestamp,` +
		selectAgendaVotesQuery + `GROUP BY timestamp ORDER BY timestamp;`

	SelectAgendasVotesByHeight = `SELECT votes.height AS height,` +
		selectAgendaVotesQuery + `GROUP BY height ORDER BY height;`

	SelectAgendaVoteTotals = `SELECT ` + selectAgendaVotesQuery + `;`

	CreateProposalsTable = `` /* 152-byte string literal not displayed */

	InsertProposalsRow = insertProposalsRow + `RETURNING id;`

	UpsertProposalsRow = insertProposalsRow + `ON CONFLICT (token, time)
		DO UPDATE SET commit_sha = $3, time = $4  RETURNING id;`

	IndexProposalsTableOnToken = `CREATE UNIQUE INDEX ` + IndexOfProposalsTableOnToken +
		` ON proposals(token, time);`

	DeindexProposalsTableOnToken = `DROP INDEX ` + IndexOfProposalsTableOnToken + ` CASCADE;`

	SelectProposalsLastCommitTime = `Select time
		FROM proposals
		ORDER BY time DESC
		LIMIT 1;`

	CreateProposalVotesTable = `` /* 144-byte string literal not displayed */

	InsertProposalVotesRow = insertProposalVotesRow + `RETURNING id;`

	IndexProposalVotesTableOnProposalsID = `CREATE INDEX ` + IndexOfProposalVotesTableOnProposalsID +
		` ON proposal_votes(proposals_row_id);`

	DeindexProposalVotesTableOnProposalsID = `DROP INDEX ` + IndexOfProposalVotesTableOnProposalsID + ` CASCADE;`

	SelectProposalVotesChartData = `` /* 352-byte string literal not displayed */

)

These queries relate primarily to the stake tables ("tickets", "votes", "misses", "proposals", "proposal_votes", "agendas", and "agenda_votes").

View Source
const (
	CreateStatsTable = `` /* 155-byte string literal not displayed */

	IndexStatsOnHeight   = `CREATE UNIQUE INDEX ` + IndexOfHeightOnStatsTable + ` ON stats(height);`
	DeindexStatsOnHeight = `DROP INDEX ` + IndexOfHeightOnStatsTable + ` CASCADE;`

	UpsertStats = `` /* 196-byte string literal not displayed */

	// SelectPoolInfo selects information about the ticket pool when a block with
	// given hash was mined. The inner join serves to select only mainchain
	// blocks.
	SelectPoolInfo = `` /* 147-byte string literal not displayed */

	SelectPoolStatsAboveHeight = `
		SELECT pool_size, pool_val
		FROM stats
		WHERE height > $1
		ORDER BY height
	;`

	SelectPoolInfoByHeight = `` /* 175-byte string literal not displayed */

	SelectPoolInfoByHash = `` /* 155-byte string literal not displayed */

	SelectPoolInfoRange = `` /* 205-byte string literal not displayed */

	SelectPoolValSizeRange = `
		SELECT poolsize, poolval
		FROM stats
		WHERE height BETWEEN $1 AND $2
			AND is_mainchain
	;`
)

The stats table holds additional data beyond basic block data. row are unique on height, so this table does not retain information related to orphaned blocks.

View Source
const (
	RetrieveSysSettingsConfFile = `` /* 126-byte string literal not displayed */

	RetrieveSysSettingsServer = `` /* 354-byte string literal not displayed */

	RetrieveSysSettingsPerformance = `` /* 921-byte string literal not displayed */

	RetrieveSyncCommitSetting = `SELECT setting FROM pg_settings WHERE name='synchronous_commit';`

	RetrievePGVersion = `SELECT version();`
)

The following queries retrieve various system settings and other system information from the database server.

View Source
const (
	CreateTransactionTable = `` /* 479-byte string literal not displayed */

	// InsertTxRow inserts a new transaction row without checking for unique
	// index conflicts. This should only be used before the unique indexes are
	// created or there may be constraint violations (errors).
	InsertTxRow = insertTxRow + `RETURNING id;`

	// UpsertTxRow is an upsert (insert or update on conflict), returning the
	// inserted/updated transaction row id.
	UpsertTxRow = insertTxRow + `ON CONFLICT (tx_hash, block_hash) DO UPDATE
		SET is_valid = $22, is_mainchain = $23 RETURNING id;`

	// InsertTxRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with transactions' unique tx index, while returning the row id
	// of either the inserted row or the existing row that causes the conflict.
	// The complexity of this statement is necessary to avoid an unnecessary
	// UPSERT, which would have performance consequences. The row is not locked.
	InsertTxRowOnConflictDoNothing = `WITH ins AS (` +
		insertTxRow +
		`	ON CONFLICT (tx_hash, block_hash) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM ins
		UNION  ALL
		SELECT id FROM transactions
		WHERE  tx_hash = $8 AND block_hash = $1 -- only executed if no INSERT
		LIMIT  1;`

	// DeleteTxDuplicateRows removes rows that would violate the unique index
	// uix_tx_hashes. This should be run prior to creating the index.
	DeleteTxDuplicateRows = `` /* 191-byte string literal not displayed */

	SelectTxDupIDs = `` /* 227-byte string literal not displayed */

	DeleteTxRows = `DELETE FROM transactions
		WHERE id = ANY($1);`

	// IndexTransactionTableOnHashes creates the unique index uix_tx_hashes on
	// (tx_hash, block_hash).
	IndexTransactionTableOnHashes = `CREATE UNIQUE INDEX ` + IndexOfTransactionsTableOnHashes +
		` ON transactions(tx_hash, block_hash);`
	DeindexTransactionTableOnHashes = `DROP INDEX ` + IndexOfTransactionsTableOnHashes + ` CASCADE;`

	// Investigate removing this. block_hash is already indexed. Block index AND
	// tree are likely not important to index.  NEEDS TESTING BEFORE REMOVAL.
	IndexTransactionTableOnBlockIn = `CREATE UNIQUE INDEX ` + IndexOfTransactionsTableOnBlockInd +
		` ON transactions(block_hash, block_index, tree);`
	DeindexTransactionTableOnBlockIn = `DROP INDEX ` + IndexOfTransactionsTableOnBlockInd + ` CASCADE;`

	IndexTransactionTableOnBlockHeight = `CREATE INDEX ` + IndexOfTransactionsTableOnBlockHeight +
		` ON transactions(block_height);`
	DeindexTransactionTableOnBlockHeight = `DROP INDEX ` + IndexOfTransactionsTableOnBlockHeight + ` CASCADE;`

	SelectTxByHash = `` /* 126-byte string literal not displayed */

	SelectTxsByBlockHash = `SELECT id, tx_hash, block_index, tree, block_time
		FROM transactions WHERE block_hash = $1;`

	SelectTxBlockTimeByHash = `` /* 130-byte string literal not displayed */

	SelectFullTxByHash = `` /* 353-byte string literal not displayed */

	SelectFullTxsByHash = `` /* 343-byte string literal not displayed */

	SelectTxnsVinsByBlock = `SELECT vin_db_ids, is_valid, is_mainchain
		FROM transactions WHERE block_hash = $1;`

	SelectTxnsVinsVoutsByBlock = `SELECT vin_db_ids, vout_db_ids, is_mainchain
		FROM transactions WHERE block_hash = $1;`

	SelectTxsVinsAndVoutsIDs = `SELECT tx_type, vin_db_ids, vout_db_ids
		FROM transactions
		WHERE block_height BETWEEN $1 AND $2;`

	SelectTxsBlocksAboveHeight = `SELECT DISTINCT ON(block_height)
			block_height, block_hash
		FROM transactions
		WHERE block_height>$1
			AND is_mainchain;`

	SelectTxsBestBlock = `SELECT block_height, block_hash
		FROM transactions
		WHERE is_mainchain
		ORDER BY block_height DESC
		LIMIT 1;`

	SelectRegularTxnsVinsVoutsByBlock = `SELECT vin_db_ids, vout_db_ids, is_mainchain
		FROM transactions WHERE block_hash = $1 AND tree = 0;`

	SelectTxsBlocks = `` /* 173-byte string literal not displayed */

	UpdateRegularTxnsValidMainchainByBlock = `UPDATE transactions
		SET is_valid=$1, is_mainchain=$2
		WHERE block_hash=$3 AND tree=0;`

	UpdateRegularTxnsValidByBlock = `UPDATE transactions
		SET is_valid=$1
		WHERE block_hash=$2 AND tree=0;`

	UpdateTxnsMainchainByBlock = `UPDATE transactions
		SET is_mainchain=$1
		WHERE block_hash=$2
		RETURNING id;`

	UpdateTxnsValidMainchainAll = `` /* 196-byte string literal not displayed */

	UpdateRegularTxnsValidAll = `` /* 142-byte string literal not displayed */

	UpdateTxnsMainchainAll = `` /* 141-byte string literal not displayed */

	SelectTicketsByType = `` /* 177-byte string literal not displayed */

	SelectTxnByDbID = `SELECT block_hash, block_height, tx_hash
		FROM transactions WHERE id = $1;`

	SelectTicketsOutputCountByAllBlocks = `` /* 250-byte string literal not displayed */

	SelectTicketsOutputCountByTPWindow = `` /* 257-byte string literal not displayed */

	SelectFeesPerBlockAboveHeight = `` /* 156-byte string literal not displayed */

	SelectMixedTotalPerBlock = `` /* 200-byte string literal not displayed */

	SelectMixedVouts = `` /* 388-byte string literal not displayed */

)

These queries relate primarily to the "transactions" table.

View Source
const (
	CreateVinTable = `` /* 278-byte string literal not displayed */

	// InsertVinRow inserts a new vin row without checking for unique index
	// conflicts. This should only be used before the unique indexes are created
	// or there may be constraint violations (errors).
	InsertVinRow = insertVinRow + `RETURNING id;`

	// UpsertVinRow is an upsert (insert or update on conflict), returning the
	// inserted/updated vin row id.
	UpsertVinRow = insertVinRow + `ON CONFLICT (tx_hash, tx_index, tx_tree) DO UPDATE
		SET is_valid = $8, is_mainchain = $9, block_time = $10,
			prev_tx_hash = $4, prev_tx_index = $5, prev_tx_tree = $6
		RETURNING id;`

	// InsertVinRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with vins' unique tx index, while returning the row id of either
	// the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertVinRowOnConflictDoNothing = `WITH inserting AS (` +
		insertVinRow +
		`	ON CONFLICT (tx_hash, tx_index, tx_tree) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM inserting
		UNION  ALL
		SELECT id FROM vins
		WHERE  tx_hash = $1 AND tx_index = $2 AND tx_tree = $3 -- only executed if no INSERT
		LIMIT  1;`

	// DeleteVinsDuplicateRows removes rows that would violate the unique index
	// uix_vin. This should be run prior to creating the index.
	DeleteVinsDuplicateRows = `` /* 186-byte string literal not displayed */

	ShowCreateVinsTable     = `WITH a AS (SHOW CREATE vins) SELECT create_statement FROM a;`
	DistinctVinsToTempTable = `INSERT INTO vins_temp
		SELECT DISTINCT ON (tx_hash, tx_index) *
		FROM vins;`
	RenameVinsTemp = `ALTER TABLE vins_temp RENAME TO vins;`

	SelectVinDupIDs = `` /* 218-byte string literal not displayed */

	DeleteVinRows = `DELETE FROM vins
		WHERE id = ANY($1);`

	IndexVinTableOnVins = `CREATE UNIQUE INDEX ` + IndexOfVinsTableOnVin +
		` ON vins(tx_hash, tx_index, tx_tree);`
	DeindexVinTableOnVins = `DROP INDEX ` + IndexOfVinsTableOnVin + ` CASCADE;`

	IndexVinTableOnPrevOuts = `CREATE INDEX ` + IndexOfVinsTableOnPrevOut +
		` ON vins(prev_tx_hash, prev_tx_index);`
	DeindexVinTableOnPrevOuts = `DROP INDEX ` + IndexOfVinsTableOnPrevOut + ` CASCADE;`

	SelectVinIDsALL = `SELECT id FROM vins;`
	CountVinsRows   = `SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname='vins';`

	SetTxTypeOnVinsByVinIDs = `UPDATE vins SET tx_type=$1 WHERE id=$2;`

	SelectSpendingTxsByPrevTx                = `SELECT id, tx_hash, tx_index, prev_tx_index FROM vins WHERE prev_tx_hash=$1;`
	SelectSpendingTxsByPrevTxWithBlockHeight = `` /* 265-byte string literal not displayed */

	SelectSpendingTxByPrevOut = `` /* 152-byte string literal not displayed */

	SelectFundingTxsByTx        = `SELECT id, prev_tx_hash FROM vins WHERE tx_hash=$1;`
	SelectFundingTxByTxIn       = `SELECT id, prev_tx_hash FROM vins WHERE tx_hash=$1 AND tx_index=$2;`
	SelectFundingOutpointByTxIn = `SELECT id, prev_tx_hash, prev_tx_index, prev_tx_tree FROM vins
		WHERE tx_hash=$1 AND tx_index=$2;`

	SelectFundingOutpointByVinID     = `SELECT prev_tx_hash, prev_tx_index, prev_tx_tree FROM vins WHERE id=$1;`
	SelectFundingOutpointIndxByVinID = `SELECT prev_tx_index FROM vins WHERE id=$1;`
	SelectFundingTxByVinID           = `SELECT prev_tx_hash FROM vins WHERE id=$1;`
	SelectSpendingTxByVinID          = `SELECT tx_hash, tx_index, tx_tree FROM vins WHERE id=$1;`
	SelectAllVinInfoByID             = `` /* 158-byte string literal not displayed */

	SelectVinVoutPairByID = `SELECT tx_hash, tx_index, prev_tx_hash, prev_tx_index FROM vins WHERE id = $1;`

	SelectUTXOsViaVinsMatch = `` /* 679-byte string literal not displayed */

	SelectUTXOs = `` /* 283-byte string literal not displayed */

	SetIsValidIsMainchainByTxHash = `UPDATE vins SET is_valid = $1, is_mainchain = $2
		WHERE tx_hash = $3 AND block_time = $4;`
	SetIsValidIsMainchainByVinID = `UPDATE vins SET is_valid = $2, is_mainchain = $3
		WHERE id = $1;`
	SetIsValidByTxHash = `UPDATE vins SET is_valid = $1
		WHERE tx_hash = $2 AND block_time = $3;`
	SetIsValidByVinID = `UPDATE vins SET is_valid = $2
		WHERE id = $1;`
	SetIsMainchainByTxHash = `UPDATE vins SET is_mainchain = $1
		WHERE tx_hash = $2 AND block_time = $3;`
	SetIsMainchainByVinID = `UPDATE vins SET is_mainchain = $2
		WHERE id = $1;`

	// SetVinsTableCoinSupplyUpgrade does not set is_mainchain because that upgrade comes after this one
	SetVinsTableCoinSupplyUpgrade = `UPDATE vins SET is_valid = $1, block_time = $3, value_in = $4
		WHERE tx_hash = $5 AND tx_index = $6 AND tx_tree = $7;`

	// SelectCoinSupply fetches the newly minted atoms per block by filtering
	// for stakebase and stake-validated coinbase transactions.
	SelectCoinSupply = `` /* 416-byte string literal not displayed */

	CreateVoutTable = `` /* 286-byte string literal not displayed */

	// InsertVoutRow inserts a new vout row without checking for unique index
	// conflicts. This should only be used before the unique indexes are created
	// or there may be constraint violations (errors).
	InsertVoutRow = insertVoutRow + `RETURNING id;`

	// UpsertVoutRow is an upsert (insert or update on conflict), returning the
	// inserted/updated vout row id.
	UpsertVoutRow = insertVoutRow + `ON CONFLICT (tx_hash, tx_index, tx_tree) DO UPDATE
		SET version = $5 RETURNING id;`

	UpdateVoutSpendTxRowID  = `UPDATE vouts SET spend_tx_row_id = $1 WHERE id = $2;`
	UpdateVoutsSpendTxRowID = `UPDATE vouts SET spend_tx_row_id = $1 WHERE id = ANY($2);`
	ResetVoutSpendTxRowIDs  = `UPDATE vouts SET spend_tx_row_id = NULL WHERE id = ANY($1);`

	// InsertVoutRowOnConflictDoNothing allows an INSERT with a DO NOTHING on
	// conflict with vouts' unique tx index, while returning the row id of
	// either the inserted row or the existing row that causes the conflict. The
	// complexity of this statement is necessary to avoid an unnecessary UPSERT,
	// which would have performance consequences. The row is not locked.
	InsertVoutRowOnConflictDoNothing = `WITH inserting AS (` +
		insertVoutRow +
		`	ON CONFLICT (tx_hash, tx_index, tx_tree) DO NOTHING -- no lock on row
			RETURNING id
		)
		SELECT id FROM inserting
		UNION  ALL
		SELECT id FROM vouts
		WHERE  tx_hash = $1 AND tx_index = $2 AND tx_tree = $3 -- only executed if no INSERT
		LIMIT  1;`

	// DeleteVoutDuplicateRows removes rows that would violate the unique index
	// uix_vout_txhash_ind. This should be run prior to creating the index.
	DeleteVoutDuplicateRows = `` /* 188-byte string literal not displayed */

	ShowCreateVoutsTable     = `WITH a AS (SHOW CREATE vouts) SELECT create_statement FROM a;`
	DistinctVoutsToTempTable = `INSERT INTO vouts_temp
		SELECT DISTINCT ON (tx_hash, tx_index) *
		FROM vouts;`
	RenameVoutsTemp = `ALTER TABLE vouts_temp RENAME TO vouts;`

	SelectVoutDupIDs = `` /* 219-byte string literal not displayed */

	DeleteVoutRows = `DELETE FROM vins
		WHERE id = ANY($1);`

	// IndexVoutTableOnTxHashIdx creates the unique index uix_vout_txhash_ind on
	// (tx_hash, tx_index, tx_tree).
	IndexVoutTableOnTxHashIdx = `CREATE UNIQUE INDEX IF NOT EXISTS ` + IndexOfVoutsTableOnTxHashInd +
		` ON vouts(tx_hash, tx_index, tx_tree);`
	DeindexVoutTableOnTxHashIdx = `DROP INDEX IF EXISTS ` + IndexOfVoutsTableOnTxHashInd + ` CASCADE;`

	IndexVoutTableOnSpendTxID = `CREATE INDEX IF NOT EXISTS ` + IndexOfVoutsTableOnSpendTxID +
		` ON vouts(spend_tx_row_id);`
	DeindexVoutTableOnSpendTxID = `DROP INDEX IF EXISTS ` + IndexOfVoutsTableOnSpendTxID + ` CASCADE;`

	SelectAddressByTxHash = `SELECT id, script_addresses, value, mixed FROM vouts
		WHERE tx_hash = $1 AND tx_index = $2 AND tx_tree = $3;`

	SelectPkScriptByID       = `SELECT version, pkscript FROM vouts WHERE id=$1;`
	SelectPkScriptByOutpoint = `SELECT version, pkscript FROM vouts WHERE tx_hash=$1 and tx_index=$2;`
	SelectPkScriptByVinID    = `` /* 140-byte string literal not displayed */

	SelectVoutIDByOutpoint = `SELECT id FROM vouts WHERE tx_hash=$1 and tx_index=$2;`
	SelectVoutByID         = `SELECT * FROM vouts WHERE id=$1;`

	RetrieveVoutValue  = `SELECT value FROM vouts WHERE tx_hash=$1 and tx_index=$2;`
	RetrieveVoutValues = `SELECT value, tx_index, tx_tree FROM vouts WHERE tx_hash=$1;`
)

These queries relate primarily to the "vins" and "vouts" tables.

Variables

AddressesIndexNames are the names of the indexes on the addresses table.

View Source
var IndexDescriptions = map[string]string{
	IndexOfBlocksTableOnHash:               "blocks on hash",
	IndexOfBlocksTableOnHeight:             "blocks on height",
	IndexOfTransactionsTableOnHashes:       "transactions on block hash and transaction hash",
	IndexOfTransactionsTableOnBlockInd:     "transactions on block hash, block index, and tx tree",
	IndexOfTransactionsTableOnBlockHeight:  "transactions on block height",
	IndexOfVinsTableOnVin:                  "vins on transaction hash and index",
	IndexOfVinsTableOnPrevOut:              "vins on previous outpoint",
	IndexOfVoutsTableOnTxHashInd:           "vouts on transaction hash and index",
	IndexOfVoutsTableOnSpendTxID:           "vouts on spend_tx_row_id",
	IndexOfAddressTableOnAddress:           "addresses table on address",
	IndexOfAddressTableOnVoutID:            "addresses table on vout row id, address, and is_funding",
	IndexOfAddressTableOnBlockTime:         "addresses table on block time",
	IndexOfAddressTableOnTx:                "addresses table on transaction hash",
	IndexOfAddressTableOnMatchingTx:        "addresses table on matching tx hash",
	IndexOfTicketsTableOnHashes:            "tickets table on block hash and transaction hash",
	IndexOfTicketsTableOnTxRowID:           "tickets table on transactions table row ID",
	IndexOfTicketsTableOnPoolStatus:        "tickets table on pool status",
	IndexOfVotesTableOnHashes:              "votes table on block hash and transaction hash",
	IndexOfVotesTableOnBlockHash:           "votes table on block hash",
	IndexOfVotesTableOnCandBlock:           "votes table on candidate block",
	IndexOfVotesTableOnVersion:             "votes table on vote version",
	IndexOfVotesTableOnHeight:              "votes table on height",
	IndexOfVotesTableOnBlockTime:           "votes table on block time",
	IndexOfMissesTableOnHashes:             "misses on ticket hash and block hash",
	IndexOfAgendasTableOnName:              "agendas on agenda name",
	IndexOfAgendaVotesTableOnRowIDs:        "agenda_votes on votes table row ID and agendas table row ID",
	IndexOfProposalsTableOnToken:           "proposals on token and time",
	IndexOfProposalVotesTableOnProposalsID: "proposal_votes on proposals row ID",
	IndexOfHeightOnStatsTable:              "stats table on height",
}

IndexDescriptions relate table index names to descriptions of the indexes.

View Source
var (
	SelectAllRevokes = fmt.Sprintf(`SELECT id, tx_hash, block_height, vin_db_ids[0]
		FROM transactions
		WHERE tx_type = %d;`,
		stake.TxTypeSSRtx)
)

Functions

func BlockInsertStatement

func BlockInsertStatement(checked bool) string

func MakeAddressRowInsertStatement

func MakeAddressRowInsertStatement(checked, updateOnConflict bool) string

MakeAddressRowInsertStatement returns the appropriate addresses insert statement for the desired conflict checking and handling behavior. For checked=false, no ON CONFLICT checks will be performed, and the value of updateOnConflict is ignored. This should only be used prior to creating the unique indexes as these constraints will cause an errors if an inserted row violates a constraint. For updateOnConflict=true, an upsert statement will be provided that UPDATEs the conflicting row. For updateOnConflict=false, the statement will either insert or do nothing, and return the inserted (new) or conflicting (unmodified) row id.

func MakeAgendaInsertStatement

func MakeAgendaInsertStatement(checked bool) string

MakeAgendaInsertStatement returns the appropriate agendas insert statement for the desired conflict checking and handling behavior. See the description of MakeTicketInsertStatement for details.

func MakeAgendaVotesInsertStatement

func MakeAgendaVotesInsertStatement(checked bool) string

MakeAgendaVotesInsertStatement returns the appropriate agenda votes insert statement for the desired conflict checking and handling behavior. See the description of MakeTicketInsertStatement for details.

func MakeMissInsertStatement

func MakeMissInsertStatement(checked, updateOnConflict bool) string

MakeMissInsertStatement returns the appropriate misses insert statement for the desired conflict checking and handling behavior. See the description of MakeTicketInsertStatement for details.

func MakeProposalsInsertStatement

func MakeProposalsInsertStatement(checked bool) string

MakeProposalsInsertStatement returns the appropriate proposals insert statement for the desired conflict checking and handling behavior. See the description of MakeTicketInsertStatement for details.

func MakeSelectAddressAmountFlowByAddress

func MakeSelectAddressAmountFlowByAddress(group string) string

MakeSelectAddressAmountFlowByAddress returns the selectAddressAmountFlowByAddress query

func MakeSelectAddressTimeGroupingCount

func MakeSelectAddressTimeGroupingCount(group string) string

func MakeSelectAddressTxTypesByAddress

func MakeSelectAddressTxTypesByAddress(group string) string

MakeSelectAddressTxTypesByAddress returns the selectAddressTxTypesByAddress query

func MakeSelectTicketsByPurchaseDate

func MakeSelectTicketsByPurchaseDate(group string) string

MakeSelectTicketsByPurchaseDate returns the selectTicketsByPurchaseDate query

func MakeTicketInsertStatement

func MakeTicketInsertStatement(checked, updateOnConflict bool) string

MakeTicketInsertStatement returns the appropriate tickets insert statement for the desired conflict checking and handling behavior. For checked=false, no ON CONFLICT checks will be performed, and the value of updateOnConflict is ignored. This should only be used prior to creating the unique indexes as these constraints will cause an errors if an inserted row violates a constraint. For updateOnConflict=true, an upsert statement will be provided that UPDATEs the conflicting row. For updateOnConflict=false, the statement will either insert or do nothing, and return the inserted (new) or conflicting (unmodified) row id.

func MakeTxInsertStatement

func MakeTxInsertStatement(checked, updateOnConflict bool) string

MakeTxInsertStatement returns the appropriate transaction insert statement for the desired conflict checking and handling behavior. For checked=false, no ON CONFLICT checks will be performed, and the value of updateOnConflict is ignored. This should only be used prior to creating the unique indexes as these constraints will cause an errors if an inserted row violates a constraint. For updateOnConflict=true, an upsert statement will be provided that UPDATEs the conflicting row. For updateOnConflict=false, the statement will either insert or do nothing, and return the inserted (new) or conflicting (unmodified) row id.

func MakeVinInsertStatement

func MakeVinInsertStatement(checked, updateOnConflict bool) string

MakeVinInsertStatement returns the appropriate vins insert statement for the desired conflict checking and handling behavior. For checked=false, no ON CONFLICT checks will be performed, and the value of updateOnConflict is ignored. This should only be used prior to creating the unique indexes as these constraints will cause an errors if an inserted row violates a constraint. For updateOnConflict=true, an upsert statement will be provided that UPDATEs the conflicting row. For updateOnConflict=false, the statement will either insert or do nothing, and return the inserted (new) or conflicting (unmodified) row id.

func MakeVoteInsertStatement

func MakeVoteInsertStatement(checked, updateOnConflict bool) string

MakeVoteInsertStatement returns the appropriate votes insert statement for the desired conflict checking and handling behavior. See the description of MakeTicketInsertStatement for details.

func MakeVoutInsertStatement

func MakeVoutInsertStatement(checked, updateOnConflict bool) string

MakeVoutInsertStatement returns the appropriate vouts insert statement for the desired conflict checking and handling behavior. For checked=false, no ON CONFLICT checks will be performed, and the value of updateOnConflict is ignored. This should only be used prior to creating the unique indexes as these constraints will cause an errors if an inserted row violates a constraint. For updateOnConflict=true, an upsert statement will be provided that UPDATEs the conflicting row. For updateOnConflict=false, the statement will either insert or do nothing, and return the inserted (new) or conflicting (unmodified) row id.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL