@@ -387,6 +387,12 @@ export class SqlDriver implements Driver {
387387 case 'file' :
388388 case 'avatar' :
389389 case 'location' : col = table . json ( name ) ; break ;
390+ case 'lookup' :
391+ col = table . string ( name ) ;
392+ if ( field . reference_to ) {
393+ table . foreign ( name ) . references ( 'id' ) . inTable ( field . reference_to ) ;
394+ }
395+ break ;
390396 case 'summary' : col = table . float ( name ) ; break ; // Stored calculation result
391397 case 'auto_number' : col = table . string ( name ) ; break ; // Generated string
392398 case 'formula' : return ; // Virtual field, do not create column
@@ -532,6 +538,17 @@ export class SqlDriver implements Driver {
532538 const columns = await this . introspectColumns ( tableName ) ;
533539 const foreignKeys = await this . introspectForeignKeys ( tableName ) ;
534540 const primaryKeys = await this . introspectPrimaryKeys ( tableName ) ;
541+ const uniqueConstraints = await this . introspectUniqueConstraints ( tableName ) ;
542+
543+ // Update columns with primary key and unique information
544+ for ( const col of columns ) {
545+ if ( primaryKeys . includes ( col . name ) ) {
546+ col . isPrimary = true ;
547+ }
548+ if ( uniqueConstraints . includes ( col . name ) ) {
549+ col . isUnique = true ;
550+ }
551+ }
535552
536553 tables [ tableName ] = {
537554 name : tableName ,
@@ -730,6 +747,72 @@ export class SqlDriver implements Driver {
730747 return primaryKeys ;
731748 }
732749
750+ /**
751+ * Get unique constraint information for a specific table.
752+ */
753+ private async introspectUniqueConstraints ( tableName : string ) : Promise < string [ ] > {
754+ const uniqueColumns : string [ ] = [ ] ;
755+
756+ try {
757+ if ( this . config . client === 'pg' || this . config . client === 'postgresql' ) {
758+ const result = await this . knex . raw ( `
759+ SELECT c.column_name
760+ FROM information_schema.table_constraints tc
761+ JOIN information_schema.constraint_column_usage AS ccu
762+ ON tc.constraint_schema = ccu.constraint_schema
763+ AND tc.constraint_name = ccu.constraint_name
764+ WHERE tc.constraint_type = 'UNIQUE'
765+ AND tc.table_name = ?
766+ ` , [ tableName ] ) ;
767+
768+ for ( const row of result . rows ) {
769+ uniqueColumns . push ( row . column_name ) ;
770+ }
771+ } else if ( this . config . client === 'mysql' || this . config . client === 'mysql2' ) {
772+ const result = await this . knex . raw ( `
773+ SELECT COLUMN_NAME
774+ FROM information_schema.TABLE_CONSTRAINTS tc
775+ JOIN information_schema.KEY_COLUMN_USAGE kcu
776+ USING (CONSTRAINT_NAME, TABLE_SCHEMA, TABLE_NAME)
777+ WHERE CONSTRAINT_TYPE = 'UNIQUE'
778+ AND TABLE_SCHEMA = DATABASE()
779+ AND TABLE_NAME = ?
780+ ` , [ tableName ] ) ;
781+
782+ for ( const row of result [ 0 ] ) {
783+ uniqueColumns . push ( row . COLUMN_NAME ) ;
784+ }
785+ } else if ( this . config . client === 'sqlite3' ) {
786+ const safeTableName = tableName . replace ( / [ ^ a - z A - Z 0 - 9 _ ] / g, '' ) ;
787+
788+ // Validate table exists
789+ const tablesResult = await this . knex . raw ( "SELECT name FROM sqlite_master WHERE type = 'table'" ) ;
790+ const tableNames = Array . isArray ( tablesResult ) ? tablesResult . map ( ( row : any ) => row . name ) : [ ] ;
791+
792+ if ( ! tableNames . includes ( safeTableName ) ) {
793+ return uniqueColumns ;
794+ }
795+
796+ const indexes = await this . knex . raw ( `PRAGMA index_list(${ safeTableName } )` ) ;
797+
798+ for ( const idx of indexes ) {
799+ // Check if unique
800+ if ( idx . unique === 1 ) {
801+ const info = await this . knex . raw ( `PRAGMA index_info(${ idx . name } )` ) ;
802+ // Only handle single column unique constraints for now
803+ if ( info . length === 1 ) {
804+ uniqueColumns . push ( info [ 0 ] . name ) ;
805+ }
806+ }
807+ }
808+ }
809+ } catch ( error ) {
810+ console . warn ( 'Could not introspect unique constraints for a table:' , error ) ;
811+ }
812+
813+ return uniqueColumns ;
814+ }
815+
733816 async disconnect ( ) {
734817 await this . knex . destroy ( ) ;
735818 }
0 commit comments