Example #1
0
        /// <summary>
        /// unpack the json value and set all custom values in the row
        /// </summary>
        private void SetRowFromCustomValues(string json, TableDef tabledef, Row row)
        {
            var customs = JsonConvert.DeserializeObject <JObject>(json, Constants.CamelSerializerSettings);

            foreach (var coldef in tabledef.Cols.Where(c => c.IsCustom))
            {
                var node = customs[coldef.Name];
                if (node == null)
                {
                    continue;
                }
                object value = Retrovert.ParseNode(node, coldef.CSType);
                row.SetCustom(coldef.Name, value);
            }
        }
        /// <summary>
        /// Convert a dictionary of custom values indexed by custom column name into json format for database storage
        /// </summary>
        public string CustomValuesToJson(TableDef tabldef, Dictionary <string, object> values)
        {
            var buf    = new StringBuilder(values.Count * 20);
            var wri0   = new StringWriter(buf);
            var writer = new JsonTextWriter(wri0);

            writer.WriteStartObject();
            foreach (var coldef in tabldef.Cols.Where(c => c.IsCustom))
            {
                if (!values.TryGetValue(coldef.Name, out object value))
                {
                    continue;
                }
                writer.WritePropertyName(coldef.Name);
                writer.WriteRawValue(Retrovert.FormatRawJsonValue(coldef, value));
            }
            writer.WriteEndObject();
            return(buf.ToString());
        }
Example #3
0
        /// <summary>
        /// if persiston was new, figure out new main row's key and set Modified.Key
        /// </summary>
        private static void AssignPersistonKey(SaveItem item)
        {
            if (!item.Modified.Key.IsNew)
            {
                return;
            }
            var mainTdef = item.DatonDef.MainTableDef;
            var r        = RecurPoint.FromDaton(item.DatonDef, item.Modified);

            if (r is RowRecurPoint rr)
            {
                object pk       = mainTdef.RowType.GetField(mainTdef.PrimaryKeyColName).GetValue(rr.Row);
                var    pkdef    = mainTdef.Cols.Single(c => c.Name == mainTdef.PrimaryKeyColName);
                string pkString = Retrovert.FormatRawJsonValue(pkdef, pk);
                item.Modified.Key = new PersistonKey(item.Modified.Key.Name, pkString, false);
                return;
            }

            //if reached here, client semantics was unexpected: it should have sent a new persiston only for a daton type
            //that defines a single main row; in all other cases the client should have loaded then modified an existing
            //persiston, even if it had no rows in it.
            throw new Exception("Cannot save a whole-table persiston with a daton-key identifying a primary key");
        }
Example #4
0
        private async Task HandleHttpMain(MainRequest req, IUser user, MainResponse resp)
        {
            //initialize
            if (req.Initialze != null)
            {
                resp.DataDictionary = Retrovert.DataDictionaryToWire(DataDictionary, user, LanguageMessages);
            }

            //load datons
            if (req.GetDatons != null)
            {
                var getResponses = new List <GetDatonResponse>();
                foreach (var drequest in req.GetDatons)
                {
                    var loadResult = await GetDaton(DatonKey.Parse(drequest.Key), user, forceCheckLatest : drequest.ForceLoad);

                    var getResponse = new GetDatonResponse
                    {
                        Errors = loadResult.Errors
                    };
                    if (loadResult.Daton != null)                                                                                      //null means it was not found by key, usually
                    {
                        bool doReturnToCaller = loadResult.Daton.Version == null || drequest.KnownVersion != loadResult.Daton.Version; //omit if client already has the current version
                        if (doReturnToCaller)
                        {
                            getResponse.CondensedDaton = new CondensedDatonResponse
                            {
                                CondensedDatonJson = Retrovert.ToWire(DataDictionary, loadResult.Daton, false)
                            };
                        }
                        if (drequest.DoSubscribe && loadResult.Daton is Persiston)
                        {
                            ClientPlex.ManageSubscribe(req.SessionKey, loadResult.Daton.Key, loadResult.Daton.Version, true);
                        }
                    }
                    else
                    {
                        getResponse.Key = drequest.Key; //only needed if daton is not returned to client
                    }
                    getResponses.Add(getResponse);
                }
                resp.GetDatons = getResponses.ToArray();
            }

            //save datons
            if (req.SaveDatons != null)
            {
                var diffs = new List <PersistonDiff>();
                foreach (var saveRequest in req.SaveDatons)
                {
                    var diff = Retrovert.FromDiff(DataDictionary, saveRequest);
                    diffs.Add(diff);
                }
                (bool success, var results) = await SaveDatons(req.SessionKey, user, diffs.ToArray());

                var saveResponses = new List <SavePersistonResponse>();
                foreach (var result in results)
                {
                    saveResponses.Add(new SavePersistonResponse
                    {
                        IsDeleted = result.IsDeleted,
                        IsSuccess = result.IsSuccess,
                        OldKey    = result.OldKey.ToString(),
                        NewKey    = result.NewKey?.ToString(),
                        Errors    = result.Errors
                    });
                }
                resp.SavedPersistons       = saveResponses.ToArray();
                resp.SavePersistonsSuccess = success;
            }

            //change datons state
            if (req.ManageDatons != null)
            {
                var manageResponses = new List <ManageDatonResponse>(req.ManageDatons.Length);
                foreach (var mrequest in req.ManageDatons)
                {
                    //what does the caller wants to change?
                    var  datonKey       = DatonKey.Parse(mrequest.Key);
                    bool wantsLock      = mrequest.SubscribeState == 2;
                    bool wantsSubscribe = mrequest.SubscribeState >= 1;

                    //handle change in subscription
                    //(Performance note: unsubscribe should happen before unlock so that the unlock-propogation can short circuit reloading. Ultimately
                    //if only one client is dealing with a daton and that client releases the lock and subscription, this server can forget about it
                    //immediately.)
                    bool isSubscribed = false;
                    if (datonKey is PersistonKey)
                    {
                        ClientPlex.ManageSubscribe(req.SessionKey, datonKey, mrequest.Version, wantsSubscribe);
                        isSubscribed = wantsSubscribe;
                    }

                    //handle change in lock
                    string lockErrorCode = "";
                    bool   hasLock       = false;
                    if (wantsLock)
                    {
                        if (string.IsNullOrEmpty(mrequest.Version))
                        {
                            throw new Exception("Version required to lock daton");
                        }
                        (hasLock, lockErrorCode) = LockManager.RequestLock(datonKey, mrequest.Version, req.SessionKey);
                    }
                    else
                    {
                        LockManager.ReleaseLock(datonKey, req.SessionKey);
                    }

                    manageResponses.Add(new ManageDatonResponse
                    {
                        ErrorCode      = lockErrorCode,
                        Key            = mrequest.Key,
                        SubscribeState = hasLock ? 2 : (isSubscribed ? 1 : 0)
                    });
                }
                resp.ManageDatons = manageResponses.ToArray();
            }

            //quit - free up locks and memory
            if (req.DoQuit)
            {
                ClientPlex.DeleteSession(req.SessionKey);
                LockManager.ReleaseLocksForSession(req.SessionKey);
            }
        }
        public void ExportWhereClause(SqlSelectBuilder.Where w, SqlFlavorizer sqlFlavor)
        {
            //numeric ranges
            if (Utils.IsSupportedNumericType(ColDef.CSType))
            {
                try
                {
                    (string lo, string hi) = SplitOnTilde(PackedValue);
                    if (lo != null)
                    {
                        decimal dlo = decimal.Parse(lo);
                        w.AddWhere($"{ColDef.Name}>={w.NextParameterName()}", dlo);
                    }
                    if (hi != null)
                    {
                        decimal dhi = decimal.Parse(hi);
                        w.AddWhere($"{ColDef.Name}<={w.NextParameterName()}", dhi);
                    }
                }
                catch
                {
                    throw new Exception($"Misformatted numeric parameter: {PackedValue}");
                }
            }

            //dates and times
            else if (ColDef.CSType == typeof(DateTime))
            {
                bool isDateOnly = ColDef.WireType == Constants.TYPE_DATE;
                (string lo, string hi) = SplitOnTilde(PackedValue);
                if (lo != null)
                {
                    var dlo = Retrovert.ParseRetroDateTime(lo, isDateOnly);
                    w.AddWhere($"{ColDef.Name}>={w.NextParameterName()}", dlo);
                }
                if (hi != null)
                {
                    var dhi = Retrovert.ParseRetroDateTime(hi, isDateOnly);
                    w.AddWhere($"{ColDef.Name}<={w.NextParameterName()}", dhi);
                }
            }

            else if (ColDef.CSType == typeof(bool))
            {
                bool b;
                if (PackedValue == "0")
                {
                    b = false;
                }
                else if (PackedValue == "1")
                {
                    b = true;
                }
                else
                {
                    throw new Exception($"Boolean parameter must be 0 or 1: {PackedValue}");
                }
                w.AddWhere($"{ColDef.Name}={w.NextParameterName()}", b);
            }

            else if (ColDef.CSType == typeof(string))
            {
                w.AddWhere($"{ColDef.Name} {sqlFlavor.LikeOperator()} {w.NextParameterName()}", sqlFlavor.LikeParamValue(PackedValue));
            }

            else
            {
                throw new Exception($"Type {ColDef.CSType.Name} not supported as a viewon parameter");
            }
        }