예제 #1
0
        // Get a catalog value by entry from database or catalog
        public TypedValue GetValue(CatalogEntry entry)
        {
            if (entry.IsDatabase)
            {
                if (_catalog.SqlFlag)
                {
                    // Database sql comes from external table
                    var table = DataTableSql.Create(entry.Name, entry.DataType.Heading);
                    return(RelationValue.Create(table));
                }
                else if (!entry.IsLoaded) // lazy load

                // Database non-sql lazy loaded from store on path, then in catalog
                {
                    var value = Persist.Create(_catalog.DatabasePath, true).Load(entry.Name);
                    if (entry.DataType != value.DataType)
                    {
                        throw ProgramError.Fatal("Catalog", "Type mismatch for variable {0}", entry.Name);
                    }
                    entry.IsLoaded = true;
                    return(Persist.Create(_catalog.DatabasePath, true).Load(entry.Name));
                }
            }
            // Non-database exists only in the catalog
            return(entry.Value);
        }
예제 #2
0
        // Create a row from a heading by converting a value
        public TupleValue RowC(TypedValue hdgarg, TypedValue[] valuearg)
        {
            var     heading = hdgarg.AsHeading();
            var     value   = valuearg[0];
            DataRow newrow  = null;

            if (value.DataType is DataTypeTuple)
            {
                newrow = value.AsRow();
            }
            else if (value.DataType is DataTypeUser)
            {
                var user = value as UserValue;
                newrow = DataRow.Create(user.Heading, user.Value);
            }
            else if (value.DataType is DataTypeRelation)
            {
                var rel = value.AsTable();
                newrow = rel.GetRows().FirstOrDefault();
                if (newrow == null)
                {
                    throw ProgramError.Fatal("Builtin", "relation is empty");
                }
            }
            Logger.Assert(newrow != null, "RowT");
            Logger.WriteLine(3, "[Row={0}]", newrow);
            return(TupleValue.Create(newrow));
        }
예제 #3
0
        public override DataTable Read(string file, DataHeading heading)
        {
            var path = GetPath(file);

            if (!File.Exists(path))
            {
                return(null);
            }
            var table = DataTableLocal.Create(heading);

            using (var rdr = new TextFieldParser(path)
            {
                TextFieldType = FieldType.Delimited,
                Delimiters = new string[] { "," },
            }) {
                for (var id = 0; !rdr.EndOfData; ++id)
                {
                    var row = rdr.ReadFields();
                    if (id > 0)
                    {
                        if (_hasid)
                        {
                            row = (new string[] { id.ToString() })
                                  .Concat(row).ToArray();
                        }
                        try {
                            table.AddRow(row);
                        } catch (Exception ex) {
                            throw ProgramError.Fatal("Source Csv", "Error in row {0} of {1}: {2}", id, path, ex.Message);
                        }
                    }
                }
            }
            return(table);
        }
예제 #4
0
        //--- updates

        // Execute an update using a JOIN op
        // Only INSERT and DELETE actually supported
        public override DataTable UpdateJoin(DataTable other, JoinOps joinops)
        {
            switch (joinops)
            {
            case JoinOps.UNION:
                if (other is DataTableSql)
                {
                    InsertValuesQuery(other as DataTableSql);
                }
                else
                {
                    InsertValuesSingly(other);
                }
                return(this);

            case JoinOps.MINUS:
                if (other is DataTableSql)
                {
                    DeleteValuesQuery(other as DataTableSql);
                }
                else
                {
                    DeleteValuesSingly(other);
                }
                return(this);
            }
            throw ProgramError.Fatal("Sql data", "join operation not supported: {0}", joinops);
        }
예제 #5
0
 public NumberValue BinaryGet(BinaryValue value, NumberValue index)
 {
     if (index.Value < 0 || index.Value > value.Value.Length)
     {
         throw ProgramError.Fatal("Binary", "get index out of range");
     }
     return(NumberValue.Create(value.Value[(int)index.Value]));
 }
예제 #6
0
 // Called by the #catalog directive
 public void Directive()
 {
     if (_status > CatalogStatus.Connected)
     {
         throw ProgramError.Fatal("Catalog", "invalid catalog options");
     }
     //Connect(true);
 }
예제 #7
0
 // maybe trigger a crash
 public VoidValue Assert(BoolValue condition, TextValue message)
 {
     if (!condition.Value)
     {
         throw ProgramError.Fatal("Assert", message.Value);
     }
     return(VoidValue.Default);
 }
예제 #8
0
        public TimeValue Time(TextValue value)
        {
            DateTime t;

            if (DateTime.TryParse(value.Value, out t))
            {
                return(TimeValue.Create(t));
            }
            throw ProgramError.Fatal("Convert", "not a valid time/date");
        }
예제 #9
0
        // Obtain a text value by reading from the console/standard input output
        public TextValue Read()
        {
            var input = _input.ReadLine();

            if (input == null)
            {
                throw ProgramError.Fatal("Read", "input not available");
            }
            return(TextValue.Create(input));
        }
예제 #10
0
        // Parse string as number
        public NumberValue Number(TextValue value)
        {
            decimal d;

            if (Decimal.TryParse(value.Value, out d))
            {
                return(NumberValue.Create(d));
            }
            throw ProgramError.Fatal("Convert", "not a valid number");
        }
예제 #11
0
        // Peek the type of a variable in the database
        public DataType Peek()
        {
            if (_reader.ReadString() != Persist.Signature)
            {
                throw ProgramError.Fatal("Catalog", "load found invalid signature");
            }
            var type = ReadDataType();

            return(type);
        }
예제 #12
0
        // read the base part of a data type
        DataType ReadBaseType()
        {
            var name = _reader.ReadString();
            var type = DataTypes.Find(name);

            if (type == null)
            {
                throw ProgramError.Fatal("Storage", "Unknown type: '{0}'", name);
            }
            return(type);
        }
예제 #13
0
        public BinaryValue BinarySet(BinaryValue value, NumberValue index, NumberValue newvalue)
        {
            if (index.Value < 0 || index.Value > value.Value.Length)
            {
                throw ProgramError.Fatal("Binary", "set index out of range");
            }
            var b = value.Value.Clone() as byte[];

            b[(int)index.Value] = (byte)newvalue.Value;
            return(BinaryValue.Create(b));
        }
예제 #14
0
        protected override DbDataReader Open(string table)
        {
            var cmd = new SqlCommand(String.Format("select * from {0}", table), _connection);

            try {
                _connection.Open();
            } catch (Exception ex) {
                throw ProgramError.Fatal("Source Sql", ex.Message);
            }
            return(cmd.ExecuteReader());
        }
예제 #15
0
        ///=================================================================
        ///
        ///

        public BoolValue Bool(TextValue value)
        {
            if (String.Equals(value.Value, "true", StringComparison.InvariantCultureIgnoreCase))
            {
                return(BoolValue.True);
            }
            if (String.Equals(value.Value, "false", StringComparison.InvariantCultureIgnoreCase))
            {
                return(BoolValue.False);
            }
            throw ProgramError.Fatal("Convert", "not a valid boolean");
        }
예제 #16
0
        ///=================================================================
        ///
        /// binary operations
        ///

        public BinaryValue Binary(TypedValue value)
        {
            if (value.DataType == DataTypes.Text)
            {
                return(BinaryValue.Default); // TODO: convert text to binary
            }
            if (value.DataType == DataTypes.Number)
            {
                var size = (int)((NumberValue)value).Value;
                return(BinaryValue.Create(new byte[size]));
            }
            throw ProgramError.Fatal("Binary", "invalid arg type");
        }
예제 #17
0
 // Create a persister, in memory or to a path
 public static Persist Create(string basepath, bool cancreate)
 {
     if (!Directory.Exists(basepath))
     {
         if (!cancreate)
         {
             throw ProgramError.Fatal("Storage", "database does not exist: " + basepath);
         }
     }
     Directory.CreateDirectory(basepath);
     return(new Persist {
         _basepath = basepath
     });
 }
예제 #18
0
        // Store typed value on file stream
        public void Store(string name, TypedValue value)
        {
            var path = Path.Combine(_basepath, name + "." + VariableExtension);

            Logger.WriteLine(3, "Storing {0} {1}", name, value);
            try {
                using (var writer = new BinaryWriter(File.Open(path, FileMode.Create))) {
                    var w = PersistWriter.Create(writer);
                    w.Store(value);
                }
            } catch (Exception ex) {
                throw ProgramError.Fatal("Storage", "cannot store '{0}' : {1}", name, ex.Message);
            }
        }
예제 #19
0
        // Load the value of a variable from the database
        // Complements Store
        public TypedValue Load()
        {
            if (_reader.ReadString() != Persist.Signature)
            {
                throw ProgramError.Fatal("Catalog", "load found invalid signature");
            }
            var value = ReadValue();

            if (_reader.ReadString() != Persist.Signature)
            {
                throw ProgramError.Fatal("Catalog", "load found invalid signature");
            }
            return(value);
        }
예제 #20
0
 // Import a linked or externally held relvar
 public VoidValue Import(TextValue sourcearg, TextValue namearg, TextValue whatarg, TextValue locatorarg)
 {
     if (sourcearg.Value == Catalog.DefaultDatabaseSource)
     {
         if (!_catvars.Catalog.LinkRelvar(namearg.Value))
         {
             throw ProgramError.Fatal("Connect", "cannot link to '{0}'", namearg.Value);
         }
     }
     else if (!_catvars.Catalog.ImportRelvar(sourcearg.Value, namearg.Value, whatarg.Value, locatorarg.Value))
     {
         throw ProgramError.Fatal("Connect", "cannot import from '{0}'", namearg.Value);
     }
     return(VoidValue.Default);
 }
예제 #21
0
        // Get the value of a relation by importing some other format
        // Entry previously created by peeking
        public bool ImportRelvar(string source, string name, string what, string locator)
        {
            var entry = GlobalVars.FindEntry(name);

            Logger.Assert(entry != null, name);
            var heading = entry.DataType.Heading;
            var stream  = DataSourceStream.Create(source, locator);
            var table   = stream.Read(what, heading);

            if (table == null || !heading.Equals(table.Heading))
            {
                throw ProgramError.Fatal("Catalog", "{0} table not found: '{1}'", source, stream.GetPath(what));
            }
            GlobalVars.SetValue(entry, RelationValue.Create(table));
            return(true);
        }
예제 #22
0
        // Value replaces existing. Supports assignment.
        // Compiler is responsible for checking type and mutability state
        public void SetValue(string name, TypedValue value)
        {
            if (_catalog.IsSystem(name))
            {
                throw ProgramError.Fatal("Catalog", "cannot set '{0}'", name);
            }
            var entry = FindEntry(name);

            if (entry == null)
            {
                AddEntry(name, value.DataType, EntryKinds.Value);
                entry = FindEntry(name);
            }
            Logger.Assert(entry != null);
            SetValue(entry, value);
        }
예제 #23
0
        // Make connection to database based on available flags and current status
        // does not return on error
        void ConnectDatabase()
        {
            if (_status > CatalogStatus.Started)
            {
                return;                             // just the once
            }
            Logger.Assert(_status == CatalogStatus.Started, _status);
            Logger.WriteLine(2, $"Catalog Connect database {this}");

            // create empty catalog
            var table = DataTableLocal.Create(_catalogtableheading);

            GlobalVars.AddEntry(CatalogTableName, table.DataType, EntryKinds.Value,
                                EntryFlags.Public | EntryFlags.System, RelationValue.Create(table));
            GlobalVars.FindEntry(CatalogTableName).Flags |= EntryFlags.Database;

            // Sql or not? Open it.
            var ext = Path.GetExtension(DatabasePath);

            if (ext == "")
            {
                DatabasePath = Path.ChangeExtension(DatabasePath, (SqlFlag) ? DefaultSqlDatabaseExtension : DefaultDatabaseExtension);
            }
            SqlFlag     |= (ext == DefaultSqlDatabaseExtension || DatabaseKind != DatabaseKinds.Memory);
            DatabaseName = Path.GetFileNameWithoutExtension(DatabasePath);
            if (SqlFlag)
            {
                if (DatabaseKind == DatabaseKinds.Memory)
                {
                    DatabaseKind = DatabaseKinds.Sqlite;
                }
                Logger.WriteLine(3, "Catalog database={0} kind={1}", DatabasePath, DatabaseKind);
                if (!SqlTarget.Open(DatabasePath, DatabaseKind))
                {
                    throw ProgramError.Fatal("Catalog", "Cannot open database: {0} ({1})", DatabasePath, DatabaseKind);
                }
            }
            else
            {
                if (LoadFlag && !Directory.Exists(DatabasePath))
                {
                    throw ProgramError.Fatal("Catalog", "Database does not exist: {0}", DatabasePath);
                }
            }
            _status = CatalogStatus.Connected;
            Logger.WriteLine(3, "[CC {0}]", this);
        }
예제 #24
0
        // Factory method
        public static DataSourceOdbc Create(string locator)
        {
            var ds = new DataSourceOdbc {
                _locator = locator,
            };

            try {
                ds._connection = new OdbcConnection(locator);
            } catch (Exception ex) {
                throw ProgramError.Fatal("Source Odbc", ex.Message);
            }
            ds._convdict = new Dictionary <string, ConversionTypes> {
                { "CHAR", ConversionTypes.String },
                { "VARCHAR", ConversionTypes.String },
                { "NCHAR", ConversionTypes.String },
                { "NVARCHAR", ConversionTypes.String },
                { "INTEGER", ConversionTypes.Int },
            };
            return(ds);
        }
예제 #25
0
        public void LoadFromTable()
        {
            Logger.WriteLine(2, "Load catalog for '{0}'", DatabaseName);
            var centry = GlobalVars.FindEntry(CatalogTableName);
            var table  = GlobalVars.GetValue(centry).AsTable();

            foreach (var row in table.GetRows())
            {
                var blob = (row.Values[3] as BinaryValue).Value;
                // BUG: argLess is an attribute of a symbol but not of an ExpressionBlock, so does not round trip
                var entry = CatalogEntry.FromBinary(blob);
                PersistentVars.Add(entry);
                if (entry.IsDatabase)
                {
                    if (!LinkRelvar(entry.Name))
                    {
                        throw ProgramError.Fatal("Catalog", "cannot add '{0}'", entry.Name);
                    }
                }
            }
        }
예제 #26
0
        // Get the value of a relation from a database
        // Entry previously created by peeking
        public bool LinkRelvar(string name)
        {
            var entry = GlobalVars.FindEntry(name);

            Logger.Assert(entry != null && entry.IsDatabase);

            var heading = entry.DataType.Heading;

            if (SqlFlag)
            {
                var sqlheading = SqlTarget.Current.GetTableHeading(name);
                if (sqlheading == null)
                {
                    throw ProgramError.Fatal("Catalog", "sql table not found: '{0}'", name);
                }
                // TODO: smarter test, but still may not match exactly
                //if (!heading.Equals(sqlheading))
                if (heading.Degree != sqlheading.Degree)
                {
                    throw ProgramError.Fatal("Catalog", "sql table schema mismatch: '{0}'", name);
                }
                var table = DataTableSql.Create(name, heading);
                GlobalVars.SetValue(entry, RelationValue.Create(table));
            }
            else
            {
                var tablev = Persist.Create(DatabasePath, false).Load(name);
                if (tablev == null)
                {
                    throw ProgramError.Fatal("Catalog", "local table not found: '{0}'", name);
                }
                if (!heading.Equals(tablev.Heading))
                {
                    throw ProgramError.Fatal("Catalog", "local table schema mismatch: '{0}'", name);
                }
                GlobalVars.SetValue(entry, RelationValue.Create(tablev.AsTable()));
            }
            return(true);
        }
예제 #27
0
        // Factory method
        public static DataSourceOleDb Create(string locator)
        {
            var ds = new DataSourceOleDb {
                _locator = locator,
            };

            try {
                ds._connection = new OleDbConnection(locator);
            } catch (Exception ex) {
                throw ProgramError.Fatal("Source OleDb", ex.Message);
            }
            ds._convdict = new Dictionary <string, ConversionTypes> {
                { "DBTYPE_BOOL", ConversionTypes.Bool },
                { "DBTYPE_I4", ConversionTypes.Int },
                { "DBTYPE_DATE", ConversionTypes.DateTime },
                { "DBTYPE_WVARCHAR", ConversionTypes.String },
                { "DBTYPE_WVARLONGCHAR", ConversionTypes.String },
            };
            ds._schemadict = new Dictionary <string, ConversionTypes> {
                { "_TABLE", ConversionTypes.Bool },
            };
            return(ds);
        }
예제 #28
0
 // Final step is to load or create catalog in connected database
 void EnableCatalog()
 {
     if (_status > CatalogStatus.Connected)
     {
         return;                               // just the once
     }
     Logger.WriteLine(3, $"Catalog Enable {this}");
     Logger.Assert(_status == CatalogStatus.Connected, _status);
     // load or create catalog (but must start session first)
     if (LoadFlag)
     {
         if (!LinkRelvar(CatalogTableName))
         {
             throw ProgramError.Fatal("Catalog", "cannot load catalog for '{0}'", DatabaseName);
         }
         LoadFromTable();
         _status = CatalogStatus.Cataloguing;
     }
     else if (SaveFlag)
     {
         StoreToTable(); // create empty catalog
         _status = CatalogStatus.Cataloguing;
     }
 }
예제 #29
0
        public static DataSourceSql Create(string locator)
        {
            var ds = new DataSourceSql {
                _locator = locator,
            };

            try {
                ds._connection = new SqlConnection(locator);
            } catch (Exception ex) {
                throw ProgramError.Fatal("Source Sql", ex.Message);
            }
            ds._convdict = new Dictionary <string, ConversionTypes> {
                { "char", ConversionTypes.String },
                { "varchar", ConversionTypes.String },
                { "nchar", ConversionTypes.String },
                { "nvarchar", ConversionTypes.String },
                { "text", ConversionTypes.String },
                { "bit", ConversionTypes.Bool },
                { "int", ConversionTypes.Int },
                { "bigint", ConversionTypes.Int },
                { "smallint", ConversionTypes.Int },
                { "tinyint", ConversionTypes.Int },
                { "numeric", ConversionTypes.Decimal },
                { "decimal", ConversionTypes.Decimal },
                { "money", ConversionTypes.Decimal },
                { "smallmoney", ConversionTypes.Decimal },
                { "date", ConversionTypes.DateTime },
                { "datetime", ConversionTypes.DateTime },
                { "time", ConversionTypes.DateTime },
                { "datetime2", ConversionTypes.DateTime },
                { "smalldatetime", ConversionTypes.DateTime },
                { "datetimeoffset", ConversionTypes.DateTime },
            };

            return(ds);
        }
예제 #30
0
 // trigger an error
 public VoidValue Fail(TextValue source, TextValue message)
 {
     throw ProgramError.Fatal(source.Value, message.Value);
 }