More Roundtrip tests
This commit is contained in:
@@ -33,7 +33,7 @@ func (r *Reader) ReadDatabase() (*models.Database, error) {
|
||||
return nil, fmt.Errorf("failed to read file: %w", err)
|
||||
}
|
||||
|
||||
var dctx DCTXDictionary
|
||||
var dctx models.DCTXDictionary
|
||||
if err := xml.Unmarshal(data, &dctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse DCTX XML: %w", err)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func (r *Reader) ReadTable() (*models.Table, error) {
|
||||
}
|
||||
|
||||
// convertToDatabase converts a DCTX dictionary to a Database model
|
||||
func (r *Reader) convertToDatabase(dctx *DCTXDictionary) (*models.Database, error) {
|
||||
func (r *Reader) convertToDatabase(dctx *models.DCTXDictionary) (*models.Database, error) {
|
||||
dbName := dctx.Name
|
||||
if dbName == "" {
|
||||
dbName = "database"
|
||||
@@ -81,7 +81,7 @@ func (r *Reader) convertToDatabase(dctx *DCTXDictionary) (*models.Database, erro
|
||||
|
||||
// Create GUID mappings for tables and keys
|
||||
tableGuidMap := make(map[string]string) // GUID -> table name
|
||||
keyGuidMap := make(map[string]*DCTXKey) // GUID -> key definition
|
||||
keyGuidMap := make(map[string]*models.DCTXKey) // GUID -> key definition
|
||||
keyTableMap := make(map[string]string) // key GUID -> table name
|
||||
fieldGuidMaps := make(map[string]map[string]string) // table name -> field GUID -> field name
|
||||
|
||||
@@ -135,7 +135,7 @@ func (r *Reader) convertToDatabase(dctx *DCTXDictionary) (*models.Database, erro
|
||||
}
|
||||
|
||||
// hasSQLOption checks if a DCTX table has the SQL option set to "1"
|
||||
func (r *Reader) hasSQLOption(dctxTable *DCTXTable) bool {
|
||||
func (r *Reader) hasSQLOption(dctxTable *models.DCTXTable) bool {
|
||||
for _, option := range dctxTable.Options {
|
||||
if option.Property == "SQL" && option.PropertyValue == "1" {
|
||||
return true
|
||||
@@ -144,8 +144,21 @@ func (r *Reader) hasSQLOption(dctxTable *DCTXTable) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// collectFieldGuids recursively collects all field GUIDs from a field and its nested fields
|
||||
func (r *Reader) collectFieldGuids(dctxField *models.DCTXField, guidMap map[string]string) {
|
||||
// Store the current field's GUID if available
|
||||
if dctxField.Guid != "" && dctxField.Name != "" {
|
||||
guidMap[dctxField.Guid] = r.sanitizeName(dctxField.Name)
|
||||
}
|
||||
|
||||
// Recursively process nested fields (for GROUP types)
|
||||
for i := range dctxField.Fields {
|
||||
r.collectFieldGuids(&dctxField.Fields[i], guidMap)
|
||||
}
|
||||
}
|
||||
|
||||
// convertTable converts a DCTX table to a Table model
|
||||
func (r *Reader) convertTable(dctxTable *DCTXTable) (*models.Table, map[string]string, error) {
|
||||
func (r *Reader) convertTable(dctxTable *models.DCTXTable) (*models.Table, map[string]string, error) {
|
||||
tableName := r.sanitizeName(dctxTable.Name)
|
||||
table := models.InitTable(tableName, "public")
|
||||
table.Description = dctxTable.Description
|
||||
@@ -154,10 +167,8 @@ func (r *Reader) convertTable(dctxTable *DCTXTable) (*models.Table, map[string]s
|
||||
|
||||
// Process fields
|
||||
for _, dctxField := range dctxTable.Fields {
|
||||
// Store GUID to name mapping
|
||||
if dctxField.Guid != "" && dctxField.Name != "" {
|
||||
fieldGuidMap[dctxField.Guid] = r.sanitizeName(dctxField.Name)
|
||||
}
|
||||
// Recursively collect all field GUIDs (including nested fields in GROUP types)
|
||||
r.collectFieldGuids(&dctxField, fieldGuidMap)
|
||||
|
||||
columns, err := r.convertField(&dctxField, table.Name)
|
||||
if err != nil {
|
||||
@@ -174,7 +185,7 @@ func (r *Reader) convertTable(dctxTable *DCTXTable) (*models.Table, map[string]s
|
||||
}
|
||||
|
||||
// convertField converts a DCTX field to Column(s)
|
||||
func (r *Reader) convertField(dctxField *DCTXField, tableName string) ([]*models.Column, error) {
|
||||
func (r *Reader) convertField(dctxField *models.DCTXField, tableName string) ([]*models.Column, error) {
|
||||
var columns []*models.Column
|
||||
|
||||
// Handle GROUP fields (nested structures)
|
||||
@@ -286,7 +297,7 @@ func (r *Reader) mapDataType(clarionType string, size int) (sqlType string, prec
|
||||
}
|
||||
|
||||
// processKeys processes DCTX keys and converts them to indexes and primary keys
|
||||
func (r *Reader) processKeys(dctxTable *DCTXTable, table *models.Table, fieldGuidMap map[string]string) error {
|
||||
func (r *Reader) processKeys(dctxTable *models.DCTXTable, table *models.Table, fieldGuidMap map[string]string) error {
|
||||
for _, dctxKey := range dctxTable.Keys {
|
||||
err := r.convertKey(&dctxKey, table, fieldGuidMap)
|
||||
if err != nil {
|
||||
@@ -297,7 +308,7 @@ func (r *Reader) processKeys(dctxTable *DCTXTable, table *models.Table, fieldGui
|
||||
}
|
||||
|
||||
// convertKey converts a DCTX key to appropriate constraint/index
|
||||
func (r *Reader) convertKey(dctxKey *DCTXKey, table *models.Table, fieldGuidMap map[string]string) error {
|
||||
func (r *Reader) convertKey(dctxKey *models.DCTXKey, table *models.Table, fieldGuidMap map[string]string) error {
|
||||
var columns []string
|
||||
|
||||
// Extract column names from key components
|
||||
@@ -349,7 +360,7 @@ func (r *Reader) convertKey(dctxKey *DCTXKey, table *models.Table, fieldGuidMap
|
||||
}
|
||||
|
||||
// Handle regular index
|
||||
index := models.InitIndex(r.sanitizeName(dctxKey.Name))
|
||||
index := models.InitIndex(r.sanitizeName(dctxKey.Name), table.Name, table.Schema)
|
||||
index.Table = table.Name
|
||||
index.Schema = table.Schema
|
||||
index.Columns = columns
|
||||
@@ -361,7 +372,7 @@ func (r *Reader) convertKey(dctxKey *DCTXKey, table *models.Table, fieldGuidMap
|
||||
}
|
||||
|
||||
// processRelations processes DCTX relations and creates foreign keys
|
||||
func (r *Reader) processRelations(dctx *DCTXDictionary, schema *models.Schema, tableGuidMap map[string]string, keyGuidMap map[string]*DCTXKey, fieldGuidMaps map[string]map[string]string) error {
|
||||
func (r *Reader) processRelations(dctx *models.DCTXDictionary, schema *models.Schema, tableGuidMap map[string]string, keyGuidMap map[string]*models.DCTXKey, fieldGuidMaps map[string]map[string]string) error {
|
||||
for i := range dctx.Relations {
|
||||
relation := &dctx.Relations[i]
|
||||
// Get table names from GUIDs
|
||||
@@ -390,19 +401,23 @@ func (r *Reader) processRelations(dctx *DCTXDictionary, schema *models.Schema, t
|
||||
var fkColumns, pkColumns []string
|
||||
|
||||
// Try to use explicit field mappings
|
||||
// NOTE: DCTX format has backwards naming - ForeignMapping contains primary table fields,
|
||||
// and PrimaryMapping contains foreign table fields
|
||||
if len(relation.ForeignMappings) > 0 && len(relation.PrimaryMappings) > 0 {
|
||||
foreignFieldMap := fieldGuidMaps[foreignTableName]
|
||||
primaryFieldMap := fieldGuidMaps[primaryTableName]
|
||||
|
||||
// ForeignMapping actually contains fields from the PRIMARY table
|
||||
for _, mapping := range relation.ForeignMappings {
|
||||
if fieldName, exists := foreignFieldMap[mapping.Field]; exists {
|
||||
fkColumns = append(fkColumns, fieldName)
|
||||
if fieldName, exists := primaryFieldMap[mapping.Field]; exists {
|
||||
pkColumns = append(pkColumns, fieldName)
|
||||
}
|
||||
}
|
||||
|
||||
// PrimaryMapping actually contains fields from the FOREIGN table
|
||||
for _, mapping := range relation.PrimaryMappings {
|
||||
if fieldName, exists := primaryFieldMap[mapping.Field]; exists {
|
||||
pkColumns = append(pkColumns, fieldName)
|
||||
if fieldName, exists := foreignFieldMap[mapping.Field]; exists {
|
||||
fkColumns = append(fkColumns, fieldName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user