Ejemplo n.º 1
0
        public SDatabase Install(SAlter a, long c)
        {
            var obs = objects;

            if (a.uid >= STransaction._uid)
            {
                obs += (a.uid, a);
            }
            if (a.parent == 0)
            {
                var ot = (STable)obs[a.defpos];
                var nt = new STable(ot, a.name);
                return(New(obs + (a.defpos, nt), names - ot.name + (a.name, nt), c));
            }
            else
            {
                var ot = (STable)objects[a.parent];
                var oc = (SColumn)ot.cols[a.defpos];
                var nc = new SColumn(oc, a.name, a.dataType);
                var nt = ot + nc;
                return(New(obs + (a.defpos, nt), names + (a.name, nt), c));
            }
        }
Ejemplo n.º 2
0
        public void Server()
        {
            // client.Blocking = false;
            // process the connection string
            asy = new ServerStream(client);
            var rdr = asy.rdr;
            var wtr = asy.wtr;
            int p   = -1;

            try
            {
                var fn = rdr.GetString();
                db = SDatabase.Open(path, fn);
                wtr.Write(Types.Done);
                wtr.PutLong(0);
                wtr.PutLong(0);
                asy.Flush();
            }
            catch (IOException)
            {
                asy.Close();
                return;
            }
            catch (Exception e)
            {
                try
                {
                    asy.StartException();
                    wtr.Write(Types.Exception);
                    wtr.PutString(e.Message);
                    asy.Flush();
                }
                catch (Exception) { }
                goto _return;
            }
            // start a Strong protocol service
            for (; ;)
            {
                p = -1;
                try
                {
                    p = rdr.ReadByte();
                } catch (Exception)
                {
                    p = -1;
                }
                if (p < 0)
                {
                    goto _return;
                }
                try
                {
                    //           Console.WriteLine("[" + cid + "] Start " + ((Types)p).ToString());
                    switch ((Types)p)
                    {
                    case Types.SNames:
                    {
                        var tr = db.Transact(rdr);
                        var us = db.uids;
                        for (var b = us.PositionAt(SysTable._SysUid); b != null && b.Value.Item1 < 0; b = b.Next())
                        {
                            us -= b.Value.Item1;
                        }
                        var n = rdr.GetInt();
                        for (var i = 0; i < n; i++)
                        {
                            var u = rdr.GetLong();
                            var s = rdr.GetString();
                            if (u < rdr.lastAlias)
                            {
                                rdr.lastAlias = u;
                            }
                            us += (u, s);
                        }
                        db = new STransaction(tr, new SRole(tr.role, us));
                        break;
                    }

                    case Types.DescribedGet:
                    case Types.Get:
                    {
                        var    tr = db.Transact(rdr);
                        SQuery?qy = null;
                        try
                        {
                            qy = rdr._Get() as SQuery;
                            tr = (STransaction)rdr.db;
                        } catch (Exception e)
                        {
                            rdr.buf.len = 0;
                            throw e;
                        }
                        if (qy == null)
                        {
                            throw new StrongException("Bad query");
                        }
                        qy = (SQuery)qy.Prepare(tr, qy.Names(tr, SDict <long, long> .Empty));
                        RowSet rs = qy.RowSet(tr, qy, Context.Empty);
                        var    sb = new StringBuilder("[");
                        var    cm = "";
                        for (var b = rs?.First(); b != null; b = b.Next())
                        {
                            if (((RowBookmark)b)._ob is SRow sr && sr.isValue)
                            {
                                sb.Append(cm); cm = ",";
                                sr.Append(rs._tr, sb);
                            }
                        }
                        sb.Append(']');
                        var ts = db.curpos;
                        (db, ts) = rs._tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        if ((Types)p == Types.DescribedGet)
                        {
                            var dp = rs._qry.Display;
                            wtr.PutInt(dp.Length ?? 0);
                            for (var b = dp.First(); b != null; b = b.Next())
                            {
                                wtr.PutString(b.Value.Item2.Item2);
                            }
                        }
                        wtr.PutString(sb.ToString());
                        asy.Flush();
                        break;
                    }

                    case Types.SCreateTable:
                    {
                        var tr = db.Transact(rdr);
                        var tn = db.role[rdr.GetLong()];        // table name
                        if (db.role.globalNames.Contains(tn))
                        {
                            throw new StrongException("Duplicate table name " + tn);
                        }
                        tr     = (STransaction)tr.Install(new STable(tr), tn, tr.curpos);
                        rdr.db = tr;
                        var n = rdr.GetInt();
                        for (var i = 0; i < n; i++)
                        {
                            CreateColumn(rdr);
                        }
                        n = rdr.GetInt();
                        for (var i = 0; i < n; i++)
                        {
                            rdr.ReadByte();
                            CreateIndex(rdr);
                        }
                        var ts = db.curpos;
                        (db, ts) = rdr.db.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SCreateColumn:
                    {
                        var tr = db.Transact(rdr);
                        rdr.db = tr;
                        CreateColumn(rdr);
                        var ts = db.curpos;
                        (db, ts) = rdr.db.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SInsert:
                    {
                        var tr = db.Transact(rdr);
                        var tn = tr.role[rdr.GetLong()];
                        if (!db.role.globalNames.Contains(tn))
                        {
                            throw new StrongException("Table " + tn + " not found");
                        }
                        var tb = (STable)db.objects[db.role.globalNames[tn]];
                        rdr.context = tb;
                        var n = rdr.GetInt();
                        var c = SList <long> .Empty;
                        for (var i = 0; i < n; i++)
                        {
                            c += (rdr.GetLong(), i);
                        }
                        var ins = new SInsert(tb.uid, c, rdr);
                        tr = ins.Prepare(tr, tb.Names(tr, SDict <long, long> .Empty)).Obey(tr, Context.Empty);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.Insert:
                    {
                        var tr = db.Transact(rdr);
                        var tn = tr.role[rdr.GetLong()];
                        if (!db.role.globalNames.Contains(tn))
                        {
                            throw new StrongException("Table " + tn + " not found");
                        }
                        var tb = (STable)db.objects[db.role.globalNames[tn]];
                        rdr.context = tb;
                        var       n  = rdr.GetInt();  // # named cols
                        var       cs = SList <SColumn> .Empty;
                        Exception?ex = null;
                        for (var i = 0; i < n; i++)
                        {
                            var cn = db.role[rdr.GetLong()];
                            var ss = db.role.subs[tb.uid];
                            if (ss.defs.Contains(cn))
                            {
                                cs += ((SColumn)db.objects[ss.obs[ss.defs[cn]].Item1], i);
                            }
                            else
                            {
                                ex = new StrongException("Column " + cn + " not found");
                            }
                        }
                        var nc = rdr.GetInt();         // #cols
                        if ((n == 0 && nc != tb.cpos.Length) || (n != 0 && n != nc))
                        {
                            ex = new StrongException("Wrong number of columns");
                        }
                        var nr = rdr.GetInt();         // #records
                        for (var i = 0; i < nr; i++)
                        {
                            var f = SDict <long, Serialisable> .Empty;
                            if (n == 0)
                            {
                                for (var b = tb.cpos.First(); b != null; b = b.Next())
                                {
                                    if (b.Value.Item2 is SColumn sc)
                                    {
                                        f += (sc.uid, rdr._Get());
                                    }
                                }
                            }
                            else
                            {
                                for (var b = cs; b.Length != 0; b = b.next)
                                {
                                    f += (b.element.uid, rdr._Get());
                                }
                            }
                            tr = (STransaction)tr.Install(new SRecord(tr, tb.uid, f), tr.curpos);
                        }
                        if (ex != null)
                        {
                            throw ex;
                        }
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SAlter:
                    {
                        var tr = db.Transact(asy.rdr);
                        rdr.db = tr;
                        var at = SAlter.Get(rdr);
                        tr = (STransaction)rdr.db;
                        tr = at.Prepare(tr, SDict <long, long> .Empty)
                             .Obey(tr, Context.Empty);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SDrop:
                    {
                        var tr = db.Transact(asy.rdr);
                        var dr = SDrop.Get(rdr).Prepare(tr, SDict <long, long> .Empty);
                        tr = dr.Obey(tr, Context.Empty);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SIndex:
                    {
                        var tr = db.Transact(asy.rdr);
                        rdr.db = tr;
                        CreateIndex(rdr);
                        var ts = db.curpos;
                        (db, ts) = rdr.db.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SDropIndex:
                    {
                        var tr = db.Transact(rdr);
                        rdr.db = tr;
                        var dr = new SDropIndex(rdr);
                        tr = (STransaction)rdr.db;
                        tr = dr.Prepare(tr, SDict <long, long> .Empty)
                             .Obey(tr, Context.Empty);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.Read:
                    {
                        var id = rdr.GetLong();
                        var sb = new StringBuilder();
                        db.Get(id).Append(db, sb);
                        wtr.PutString(sb.ToString());
                        asy.Flush();
                        break;
                    }

                    case Types.SUpdateSearch:
                    {
                        var tr = db.Transact(rdr);
                        var u  = SUpdateSearch.Get(rdr);
                        tr = u.Prepare(tr, u.qry.Names(tr, SDict <long, long> .Empty)).Obey(tr, Context.Empty);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SUpdate:
                    {
                        var tr = db.Transact(rdr);
                        var id = rdr.GetLong();
                        var rc = db.Get(id);
                        var tb = (STable)tr.objects[rc.table];
                        var n  = rdr.GetInt();        // # cols updated
                        var f  = SDict <long, Serialisable> .Empty;
                        for (var i = 0; i < n; i++)
                        {
                            var cn = rdr.GetLong();
                            f += (cn, rdr._Get());
                        }
                        tr = (STransaction)tr.Install(new SUpdate(tr, rc, f), tr.curpos);
                        var ts = db.curpos;
                        (db, ts) = rdr.db.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SDeleteSearch:
                    {
                        var tr = db.Transact(rdr);
                        var dr = SDeleteSearch.Get(rdr);
                        tr = dr.Prepare(tr, dr.qry.Names(tr, SDict <long, long> .Empty)).Obey(tr, Context.Empty);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SDelete:
                    {
                        var tr = db.Transact(rdr);
                        var id = rdr.GetLong();
                        var rc = db.Get(id) as SRecord ??
                                 throw new StrongException("Record " + id + " not found");
                        tr = (STransaction)tr.Install(new SDelete(tr, rc), tr.curpos);
                        var ts = db.curpos;
                        (db, ts) = tr.MaybeAutoCommit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    case Types.SBegin:
                        db = db.Transact(rdr, false);
                        wtr.Write(Types.Done);
                        wtr.PutLong(db.curpos);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;

                    case Types.SRollback:
                        db = db.Rollback();
                        wtr.Write(Types.Done);
                        wtr.PutLong(db.curpos);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;

                    case Types.SCommit:
                    {
                        var tr = db as STransaction ??
                                 throw new StrongException("No transaction to commit");
                        var ts = db.curpos;
                        (db, ts) = tr.Commit(cid);
                        wtr.Write(Types.Done);
                        wtr.PutLong(ts);
                        wtr.PutLong(db.curpos);
                        asy.Flush();
                        break;
                    }

                    default:
                        throw new StrongException("Protocol error");
                    }
                    //           Console.WriteLine("[" + cid + "] End " + ((Types)p).ToString());
                }
                catch (SocketException)
                {
                    return;
                }
                catch (StrongException e)
                {
                    try
                    {
                        db = db.Rollback();
                        //             db.result = null;
                        asy.StartException();
                        //             Console.WriteLine(""+cid+" Reporting Exception: " + e.Message);
                        wtr.Write(Types.Exception);
                        wtr.PutString(e.Message);
                        asy.Flush();
                    }
                    catch (Exception) { }
                }
                catch (Exception e)
                {
                    try
                    {
                        db = db.Rollback();
                        //             db.result = null;
                        asy.StartException();
                        //             Console.WriteLine(""+cid+" Reporting Exception: " + e.Message);
                        wtr.Write(Types.Exception);
                        wtr.PutString(e.Message);
                        asy.Flush();
                    }
                    catch (Exception) { }
                }
            }
            _return :;
        }