@mikro-orm/sql 7.0.0-dev.231 → 7.0.0-dev.232

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -87,20 +87,61 @@ export class SchemaHelper {
87
87
  if (index.expression) {
88
88
  return index.expression;
89
89
  }
90
+ if (index.fillFactor != null && (index.fillFactor < 0 || index.fillFactor > 100)) {
91
+ throw new Error(`fillFactor must be between 0 and 100, got ${index.fillFactor} for index '${index.keyName}'`);
92
+ }
90
93
  tableName = this.quote(tableName);
91
94
  const keyName = this.quote(index.keyName);
92
95
  const defer = index.deferMode ? ` deferrable initially ${index.deferMode}` : '';
93
- let sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName} `;
96
+ let sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName}`;
94
97
  if (index.unique && index.constraint) {
95
- sql = `alter table ${tableName} add constraint ${keyName} unique `;
98
+ sql = `alter table ${tableName} add constraint ${keyName} unique`;
96
99
  }
97
100
  if (index.columnNames.some(column => column.includes('.'))) {
98
101
  // JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
99
- const sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName} `;
102
+ sql = `create ${index.unique ? 'unique ' : ''}index ${keyName} on ${tableName}`;
100
103
  const columns = this.platform.getJsonIndexDefinition(index);
101
- return `${sql}(${columns.join(', ')})${defer}`;
104
+ return `${sql} (${columns.join(', ')})${this.getCreateIndexSuffix(index)}${defer}`;
105
+ }
106
+ // Build column list with advanced options
107
+ const columns = this.getIndexColumns(index);
108
+ sql += ` (${columns})`;
109
+ // Add INCLUDE clause for covering indexes (PostgreSQL, MSSQL)
110
+ if (index.include?.length) {
111
+ sql += ` include (${index.include.map(c => this.quote(c)).join(', ')})`;
112
+ }
113
+ return sql + this.getCreateIndexSuffix(index) + defer;
114
+ }
115
+ /**
116
+ * Hook for adding driver-specific index options (e.g., fill factor for PostgreSQL).
117
+ */
118
+ getCreateIndexSuffix(_index) {
119
+ return '';
120
+ }
121
+ /**
122
+ * Build the column list for an index, supporting advanced options like sort order, nulls ordering, and collation.
123
+ * Note: Prefix length is only supported by MySQL/MariaDB which override this method.
124
+ */
125
+ getIndexColumns(index) {
126
+ if (index.columns?.length) {
127
+ return index.columns.map(col => {
128
+ let colDef = this.quote(col.name);
129
+ // Collation comes after column name (SQLite syntax: column COLLATE name)
130
+ if (col.collation) {
131
+ colDef += ` collate ${col.collation}`;
132
+ }
133
+ // Sort order
134
+ if (col.sort) {
135
+ colDef += ` ${col.sort}`;
136
+ }
137
+ // NULLS ordering (PostgreSQL)
138
+ if (col.nulls) {
139
+ colDef += ` nulls ${col.nulls}`;
140
+ }
141
+ return colDef;
142
+ }).join(', ');
102
143
  }
103
- return `${sql}(${index.columnNames.map(c => this.quote(c)).join(', ')})${defer}`;
144
+ return index.columnNames.map(c => this.quote(c)).join(', ');
104
145
  }
105
146
  getDropIndexSQL(tableName, index) {
106
147
  return `drop index ${this.quote(index.keyName)}`;
@@ -298,8 +339,20 @@ export class SchemaHelper {
298
339
  const map = {};
299
340
  indexes.forEach(index => {
300
341
  if (map[index.keyName]) {
301
- map[index.keyName].composite = true;
302
- map[index.keyName].columnNames.push(index.columnNames[0]);
342
+ if (index.columnNames.length > 0) {
343
+ map[index.keyName].composite = true;
344
+ map[index.keyName].columnNames.push(index.columnNames[0]);
345
+ }
346
+ // Merge columns array for advanced column options (sort, length, collation, etc.)
347
+ if (index.columns?.length) {
348
+ map[index.keyName].columns ??= [];
349
+ map[index.keyName].columns.push(index.columns[0]);
350
+ }
351
+ // Merge INCLUDE columns
352
+ if (index.include?.length) {
353
+ map[index.keyName].include ??= [];
354
+ map[index.keyName].include.push(index.include[0]);
355
+ }
303
356
  }
304
357
  else {
305
358
  map[index.keyName] = index;