Index Elements

The <Indices> element is a container for one or more <Index> elements. Each <Index> defines a Btrieve key (index) on the table, and contains one or more <Segment> elements describing the fields that make up the key.

In the DDF variant (Btrieve2SqlMigration), you only need to include indexes whose settings you want to override. Indexes not listed use the definitions from the DDFs.

In the Full variant (Btrieve2SqlFullMigration), all indexes must be defined completely, including every segment.

Indices Element

The <Indices> element has no attributes. It serves as a container for <Index> child elements.

<Indices>
  <Index Number="0" Unique="y" PrimaryKey="y">
    <Segment Number="1" Field="ID" Size="4" IgnoreCase="n" Descending="n"/>
  </Index>
  <Index Number="1" Unique="n" PrimaryKey="n">
    <Segment Number="1" Field="LastName" Size="30" IgnoreCase="y" Descending="n"/>
    <Segment Number="2" Field="FirstName" Size="20" IgnoreCase="y" Descending="n"/>
  </Index>
</Indices>

Index Attributes

Attribute

Required

Default

Description

Number

Yes

(none)

The Btrieve key number (0-based). This identifies which key in the Btrieve file this index corresponds to.

Unique

No

n

Whether all values in this index must be unique.

  • y — Duplicate values are not allowed.

  • n — Duplicate values are permitted.

PrimaryKey

No

n

Whether this index should be treated as the table’s primary key. Only one index should be marked as primary. In the DDF variant, setting PrimaryKey="y" overrides the automatic primary key selection. Setting PrimaryKey="n" on the current primary key removes its primary designation.

Nullable

No

no

Controls legacy null handling for the index. Determines how “null” segment values affect index behavior.

  • all — The index entry is considered null only when all segments have their respective null values.

  • any — The index entry is considered null when any segment has its null value.

  • no — The index does not participate in legacy null handling.

When an index is nullable, each segment must define a NullValue. Do not use the Default attribute on fields when using nullable indexes.

Full variant only.

Segment Element

Each <Segment> defines one part of a composite index. If a <Segment> is included for an index, all segments of that index must be listed.

Segment Attributes

Attribute

Required

Default

Description

Number

Yes

(none)

The segment number within the index (1-based). Segments are ordered by this number.

Field

Yes

(none)

The name of the field that this segment indexes. Must match a field name defined in the <Fields> section (or in the DDFs for the DDF variant). In the DDF variant, the field name is validated against the existing definition.

Size

No

(field size)

Length in bytes of the key segment. If omitted, the full size of the referenced field is used. Useful when indexing only a prefix of a string field. Full variant only.

Offset

No

(from field)

Byte offset within the record buffer for this segment. If omitted, the offset of the referenced field is used. Full variant only.

Note

This attribute is supported by the code but is not yet listed in the DTD files.

IgnoreCase

No

n

Whether to ignore character case when sorting and comparing values in this segment.

  • y — Case-insensitive (e.g., “abc” equals “ABC”).

  • n — Case-sensitive.

Descending

No

n

Whether to sort this segment’s values in descending order.

  • y — Descending (Z to A, 9 to 0).

  • n — Ascending (A to Z, 0 to 9).

NullValue

Conditional

0

The byte value (0–255) that represents “null” for this segment. Required when the parent index has Nullable set to all or any. Full variant only.

Index Behavior Notes

Unique Index Enforcement

By default, MakeIndexesUnique="y" on the <Table> element causes the driver to append primary key segments to non-unique indexes. This is required for correct Btrieve-style record positioning when using the SQL backend. If you set MakeIndexesUnique="n", certain Btrieve navigation operations (e.g., GetNext, GetPrevious from a specific position) may not work correctly.

Primary Key Selection

If no index is explicitly marked as PrimaryKey="y", the driver selects a primary key automatically:

  1. An index on an auto-increment field is preferred.

  2. If no auto-increment index exists, a synthetic MDSRECNUM column is created and used as the primary key.

The PrimaryIndex attribute on the <Table> element (Full variant) can also specify the primary index by number.