Skip to content

Invalid Foreign Key References Cause Hang **Severity:** ⚠️ CRITICAL #11

@LukasGPC

Description

@LukasGPC

Severity: ⚠️ CRITICAL

Description:
Queries that reference invalid foreign key GUIDs (GUIDs that don't exist in the referenced table) cause the driver to hang indefinitely instead of returning an error or empty result.

Symptoms:

  • Query hangs indefinitely
  • No error message or timeout
  • Graceful shutdown fails (30s timeout)
  • Connection remains open indefinitely
  • Typically discovered during authentication or data retrieval

Minimal Reproduction:

-- Step 1: Insert user with invalid org_id (GUID doesn't exist in Organization table)
INSERT INTO GPC.Platform_User (
    PUser_ID,
    PUser_Name,
    PUser_Organisation_ID
) VALUES (
    NEWID(),
    'testuser',
    '00000000-0000-0000-0000-000000000000'  -- Invalid org_id
)
func authenticateUser(db *sql.DB, username string) error {
    // Get user with invalid org_id
    var orgID string
    query1 := `SELECT PUser_Organisation_ID FROM GPC.Platform_User WHERE PUser_Name = ?`
    db.QueryRow(query1, username).Scan(&orgID)
    // orgID = "00000000-0000-0000-0000-000000000000" (doesn't exist in Organization table)

    // This query hangs indefinitely
    var orgName string
    query2 := `SELECT Org_Name FROM GPC.Organization WHERE Org_ID = ?`
    err := db.QueryRow(query2, orgID).Scan(&orgName)
    // Expected: sql.ErrNoRows
    // Actual: Hangs indefinitely ❌

    return err
}

Workaround:
Validate foreign keys exist before insert/update:

func createUser(db *sql.DB, userName, orgID string) error {
    // Validate organization exists first
    var count int
    query := `SELECT COUNT(*) FROM GPC.Organization WHERE Org_ID = ?`
    db.QueryRow(query, orgID).Scan(&count)

    if count == 0 {
        return errors.New("invalid organization ID - organization does not exist")
    }

    // Safe to insert user - org_id is valid
    insertQuery := `
        INSERT INTO GPC.Platform_User (PUser_ID, PUser_Name, PUser_Organisation_ID)
        VALUES (NEWID(), ?, ?)
    `
    _, err := db.Exec(insertQuery, userName, orgID)
    return err
}

Finding Existing Invalid Data:

-- Find users with invalid org_id
SELECT u.PUser_ID, u.PUser_Name, u.PUser_Organisation_ID
FROM GPC.Platform_User u
LEFT JOIN GPC.Organization o ON u.PUser_Organisation_ID = o.Org_ID
WHERE u.PUser_Organisation_ID IS NOT NULL
  AND o.Org_ID IS NULL;

-- Fix: Set to NULL or valid org_id
UPDATE GPC.Platform_User
SET PUser_Organisation_ID = NULL  -- or a valid org_id
WHERE PUser_ID = '<user-guid>';

Impact: High - can cause production authentication failures, requires foreign key validation before all inserts/updates.


Issue 8: UUID Field Type Warning Spam (Low Priority)

Severity: LOW (Cosmetic Only)

Description:
When reading UUID fields without CAST operations (which must be avoided due to Issue #1), the driver logs warnings for every UUID field read.

Warning Message:

fromODBC: invalid type: -11 - list.ListItem{size:0x24, itemType:0x1, data:[]uint8{...}}

Symptoms:

  • Warning logged for every UUID field in every row
  • Clutters console output and log files
  • Does not affect functionality

Example:

func listOrganizations(db *sql.DB) error {
    query := `SELECT Org_ID, Org_Name FROM GPC.Organization`
    rows, _ := db.Query(query)
    defer rows.Close()

    for rows.Next() {
        var orgID, orgName string
        rows.Scan(&orgID, &orgName) // Logs warning for Org_ID field
    }
    // Console output:
    // fromODBC: invalid type: -11 - list.ListItem{...}
    // fromODBC: invalid type: -11 - list.ListItem{...}
    // fromODBC: invalid type: -11 - list.ListItem{...}
    // (repeated for every row)

    return nil
}

Workaround:
Implement filtered log writer to suppress these warnings:

type FilteredWriter struct {
    writer io.Writer
}

func (fw *FilteredWriter) Write(p []byte) (n int, err error) {
    logMessage := string(p)

    // Filter out IRIS driver UUID warnings
    if strings.Contains(logMessage, "fromODBC: invalid type: -11") {
        return len(p), nil // Suppress this message
    }

    // Pass through all other log messages
    return fw.writer.Write(p)
}

func main() {
    // Set up filtered log output
    log.SetOutput(&FilteredWriter{writer: os.Stdout})

    // ... rest of application
}

Impact: Low - cosmetic only, but significantly clutters logs in production.


Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions