Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

Paradox database native .NET reader

, 17 Mar 2011
Read contents of a Paradox database in pure .NET code without using BDE or other libraries; index support included.
paradox-reader.zip
ParadoxTest
data
zakazky.db
zakazky.PX
zakazky.XG0
zakazky.YG0
Properties
ParadoxReader
ClassDiagram1.cd
Properties
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace ParadoxReader
{
    public class ParadoxPrimaryKey : ParadoxFile
    {
        private readonly ParadoxTable table;

        public ParadoxPrimaryKey(ParadoxTable table, string filePath)
            : base(filePath)
        {
            this.table = table;
        }

        public IEnumerable<ParadoxRecord> Enumerate(ParadoxCondition condition)
        {
            return Enumerate(condition, (ushort)(this.pxRootBlockId-1), this.pxLevelCount);
        }

        private IEnumerable<ParadoxRecord> Enumerate(ParadoxCondition condition, ushort blockId, int indexLevel)
        {
            if (indexLevel == 0)
            {
                var block = this.table.GetBlock(blockId);
                for (int i=0; i<block.RecordCount; i++)
                {
                    var rec = block[i];
                    if (condition.IsDataOk(rec))
                    {
                        yield return rec;
                    }
                }
            }
            else
            {
                var block = this.GetBlock(blockId);
                var blockIdFldIndex = this.FieldCount - 3;
                for (int i = 0; i < block.RecordCount; i++)
                {
                    var rec = block[i];
                    if (condition.IsIndexPossible(rec, i < block.RecordCount-1 ? block[i + 1] : null))
                    {
                        var qry = Enumerate(condition, (ushort)((short) rec.DataValues[blockIdFldIndex]-1), indexLevel - 1);
                        foreach (var dataRec in qry)
                        {
                            yield return dataRec;
                        }
                    }
                }
            }
        }
    }

    public abstract class ParadoxCondition
    {
        public abstract bool IsDataOk(ParadoxRecord dataRec);
        public abstract bool IsIndexPossible(ParadoxRecord indexRec, ParadoxRecord nextRec);

        public class Compare : ParadoxCondition
        {
            public ParadoxCompareOperator Operator { get; private set; }
            public object Value { get; private set; }

            public int DataFieldIndex { get; private set; }
            public int IndexFieldIndex { get; private set; }

            public override bool IsDataOk(ParadoxRecord dataRec)
            {
                var val = dataRec.DataValues[this.DataFieldIndex];
                var comp = Comparer.Default.Compare(val, this.Value);
                switch (Operator)
                {
                    case ParadoxCompareOperator.Equal:
                        return comp == 0;
                    case ParadoxCompareOperator.NotEqual:
                        return comp != 0;
                    case ParadoxCompareOperator.Greater:
                        return comp > 0;
                    case ParadoxCompareOperator.GreaterOrEqual:
                        return comp >= 0;
                    case ParadoxCompareOperator.Less:
                        return comp < 0;
                    case ParadoxCompareOperator.LessOrEqual:
                        return comp <= 0;
                    default:
                        throw new NotSupportedException();
                }
            }

            public override bool IsIndexPossible(ParadoxRecord indexRec, ParadoxRecord nextRec)
            {
                var val1 = indexRec.DataValues[this.DataFieldIndex];
                var comp1 = Comparer.Default.Compare(val1, this.Value);
                int comp2;
                if (nextRec != null)
                {
                    var val2 = nextRec.DataValues[this.DataFieldIndex];
                    comp2 = Comparer.Default.Compare(val2, this.Value);
                }
                else
                {
                    comp2 = 1; // last index range ends in infinite
                }
                switch (Operator)
                {
                    case ParadoxCompareOperator.Equal:
                        return comp1 <= 0 && comp2 >= 0;
                    case ParadoxCompareOperator.NotEqual:
                        return comp1 > 0 || comp2 < 0;
                    case ParadoxCompareOperator.Greater:
                        return comp2 > 0;
                    case ParadoxCompareOperator.GreaterOrEqual:
                        return comp2 >= 0;
                    case ParadoxCompareOperator.Less:
                        return comp1 < 0;
                    case ParadoxCompareOperator.LessOrEqual:
                        return comp1 <= 0;
                    default:
                        throw new NotSupportedException();
                }
            }

            public Compare(ParadoxCompareOperator op, object value, int dataFieldIndex, int indexFieldIndex)
            {
                Operator = op;
                Value = value;
                DataFieldIndex = dataFieldIndex;
                IndexFieldIndex = indexFieldIndex;
            }
        }

        public abstract class Multiple : ParadoxCondition
        {
            protected ParadoxCondition[] SubConditions { get; private set; }

            protected Multiple(ParadoxCondition[] subConditions)
            {
                SubConditions = subConditions;
            }

            public override bool IsDataOk(ParadoxRecord dataRec)
            {
                return this.Test(c => c.IsDataOk(dataRec));
            }

            public override bool IsIndexPossible(ParadoxRecord indexRec, ParadoxRecord nextRec)
            {
                return this.Test(c => c.IsIndexPossible(indexRec, nextRec));
            }

            protected abstract bool Test(Predicate<ParadoxCondition> test);
        }

        public class LogicalAnd : Multiple
        {
            public LogicalAnd(params ParadoxCondition[] subConditions) : base(subConditions) { }

            protected override bool Test(Predicate<ParadoxCondition> test)
            {
                foreach (var subCondition in SubConditions)
                {
                    if (!test(subCondition)) return false;
                }
                return true;
            }
        }

        public class LogicalOr : Multiple
        {
            public LogicalOr(params ParadoxCondition[] subConditions) : base(subConditions) { }

            protected override bool Test(Predicate<ParadoxCondition> test)
            {
                foreach (var subCondition in SubConditions)
                {
                    if (test(subCondition)) return true;
                }
                return false;
            }
        }
    }

    public enum ParadoxCompareOperator
    {
        Less,
        LessOrEqual,
        Equal,
        GreaterOrEqual,
        Greater,
        NotEqual
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Petr Bříza
Software Developer (Senior)
Czech Republic Czech Republic
Freelance .NET developer from Ostrava, Czech republic. Mission of my life is to find a question for the answer 42, but in the meantime I try to use .NET and surrounding technologies in behalf of mankind. I hope I bring more good than damage Smile | :)

| Advertise | Privacy | Mobile
Web02 | 2.8.140902.1 | Last Updated 17 Mar 2011
Article Copyright 2010 by Petr Bříza
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid