Ejemplo n.º 1
0
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Internal methods
         */

        /// <summary>
        /// Check to see if a field should be used for a particular action (get or set).
        ///
        /// Called by the Editor / Join class instances - not expected for general
        /// consumption - internal.
        /// </summary>
        /// <param name="action">Direction that the data is travelling  - 'get' is reading DB data, `create` and `edit` for writing to the DB</param>
        /// <param name="data">Data submitted from the client-side when setting.</param>
        /// <returns>true if the field should be used in the get / set.</returns>
        internal bool Apply(string action, Dictionary <string, object> data = null)
        {
            if (action == "get")
            {
                // Get action - can we get this field
                return(_get);
            }

            // Set - Note that validation must be done on input data before we get here.
            // Create or edit action, are we configured to use this field
            if (action == "create" && (_set == SetType.None || _set == SetType.Edit))
            {
                return(false);
            }

            if (action == "edit" && (_set == SetType.None || _set == SetType.Create))
            {
                return(false);
            }

            // Check it was in the submitted data. If not, then not required
            // (validation would have failed if it was) and therefore we don't
            // Set it. Check for a value as well, as it can come from another
            // source
            if (_setValue == null && !NestedData.InData(Name(), data))
            {
                return(false);
            }

            // In the data set, so use it
            return(true);
        }
Ejemplo n.º 2
0
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Internal methods
         */

        /// <summary>
        /// Data "get" request - get the joined data
        /// </summary>
        /// <param name="editor">Host Editor instance</param>
        /// <param name="response">DataTables response object for where the data
        /// should be written to</param>
        internal void Data(Editor editor, DtResponse response)
        {
            _Prepare(editor);

            if (response.data.Count() != 0)
            {
                // This is something that will likely come in a future version, but it
                // is a relatively low use feature. Please get in touch if this is
                // something you require.
                var pkeyA = editor.Pkey();
                if (pkeyA.Length > 1)
                {
                    throw new Exception("MJoin is not currently supported with a compound primary key for the main table.");
                }

                // If the Editor primary key is join key, then it is read automatically
                // and into Editor's primary key store
                var pkeyIsJoin = _hostField == pkeyA[0] ||
                                 _hostField == editor.Table()[0];

                // Build the basic query
                var query = editor.Db()
                            .Query("select")
                            .Distinct(true)
                            .Get(_hostField + " as dteditor_pkey")
                            .Table(editor.Table()[0]);

                if (Order() != null)
                {
                    query.Order(Order());
                }

                _ApplyWhere(query);

                foreach (var field in _fields.Where(field => field.Apply("get") && field.GetValue() == null))
                {
                    if (field.DbField().IndexOf('.') == -1)
                    {
                        query.Get(_table + "." + field.DbField() + " as " + field.DbField());
                    }
                    else
                    {
                        query.Get(field.DbField());
                    }
                }

                // Create the joins
                if (_linkTable != null)
                {
                    query.Join(_linkTable, _hostField + " = " + _linkHostField);
                    query.Join(_table, _childField + " = " + _linkChildField);
                }
                else
                {
                    query.Join(_table, _childField + " = " + _hostField);
                }

                var readField     = "";
                var joinFieldName = _hostField.Split('.')[1];
                if (NestedData.InData(_hostField, response.data[0]))
                {
                    readField = _hostField;
                }
                else if (NestedData.InData(joinFieldName, response.data[0]))
                {
                    readField = joinFieldName;
                }
                else if (!pkeyIsJoin)
                {
                    throw new Exception(
                              "Join was performed on the field '" + _hostField + "' which was not " +
                              "included in the Editor field list. The join field must be " +
                              "included as a regular field in the Editor instance."
                              );
                }

                // There appears to be a bug in the MySQL drivers for .NETCore whereby if there is
                // only one result in the original data set, then it can only read one result into
                // the new data set when using WHERE IN. Any other number of rows is fine. Tried
                // different versions of the server and driver but to no avail, so this is a workaround.
                if (editor.Db().DbType() != "mysql" || response.data.Count != 1)
                {
                    // Get list of pkey values and apply as a WHERE IN condition
                    // This is primarily useful in server-side processing mode and when filtering
                    // the table as it means only a sub-set will be selected
                    // This is only applied for "sensible" data sets. It will just complicate
                    // matters for really large data sets:
                    // https://stackoverflow.com/questions/21178390/in-clause-limitation-in-sql-server
                    if (response.data.Count < 1000)
                    {
                        var whereIn = new List <object>();

                        foreach (var data in response.data)
                        {
                            whereIn.Add(pkeyIsJoin
                                ? (data["DT_RowId"].ToString()).Replace(editor.IdPrefix(), "")
                                : NestedData.ReadProp(readField, data).ToString()
                                        );
                        }

                        query.WhereIn(_hostField, whereIn);
                    }
                }

                var result = query.Exec();

                // Map the data to the primary key for fast look up
                var join = new Dictionary <string, List <Dictionary <string, object> > >();
                Dictionary <string, object> row;

                while ((row = result.Fetch()) != null)
                {
                    var inner = new Dictionary <string, object>();

                    foreach (var field in _fields.Where(field => field.Apply("get")))
                    {
                        field.Write(inner, row);
                    }

                    var lookup = row["dteditor_pkey"].ToString();
                    if (!join.ContainsKey(lookup))
                    {
                        join.Add(lookup, new List <Dictionary <string, object> >());
                    }

                    join[lookup].Add(inner);
                }

                // Loop over the data and do a join based on the data available
                foreach (var data in response.data)
                {
                    var linkField = pkeyIsJoin
                        ? (data["DT_RowId"].ToString()).Replace(editor.IdPrefix(), "")
                        : NestedData.ReadProp(readField, data).ToString();

                    data.Add(_name, join.ContainsKey(linkField)
                        ? join[linkField]
                        : new List <Dictionary <string, object> >()
                             );
                }
            }

            // Field options
            foreach (var field in _fields)
            {
                var opts = field.OptionsExec(editor.Db());

                if (opts != null)
                {
                    response.options.Add(_name + "[]." + field.Name(), opts);
                }
            }
        }
Ejemplo n.º 3
0
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * Internal methods
         */

        /// <summary>
        /// Data "get" request - get the joined data
        /// </summary>
        /// <param name="editor">Host Editor instance</param>
        /// <param name="response">DataTables reponse object for where the data
        /// should be written to</param>
        internal void Data(Editor editor, DtResponse response)
        {
            _Prepare(editor);

            // This is something that will likely come in a future version, but it
            // is a relatively low use feature. Please get in touch if this is
            // something you require.
            var pkeyA = editor.Pkey();

            if (pkeyA.Length > 1)
            {
                throw new Exception("MJoin is not currently supported with a compound primary key for the main table.");
            }

            // If the Editor primary key is join key, then it is read automatically
            // and into Editor's primary key store
            var pkeyIsJoin = _hostField == pkeyA[0] ||
                             _hostField == editor.Table()[0];

            // Build the basic query
            var query = editor.Db()
                        .Query("select")
                        .Distinct(true)
                        .Get(_hostField + " as dteditor_pkey")
                        .Table(editor.Table()[0]);

            if (Order() != null)
            {
                query.Order(Order());
            }

            _ApplyWhere(query);

            foreach (var field in _fields.Where(field => field.Apply("get") && field.GetValue() == null))
            {
                if (field.DbField().IndexOf('.') == -1)
                {
                    query.Get(_table + "." + field.DbField() + " as " + field.DbField());
                }
                else
                {
                    query.Get(field.DbField());
                }
            }

            // Create the joins
            if (_linkTable != null)
            {
                query.Join(_linkTable, _hostField + " = " + _linkHostField);
                query.Join(_table, _childField + " = " + _linkChildField);
            }
            else
            {
                query.Join(_table, _childField + " = " + _hostField);
            }

            var result = query.Exec();

            if (result.Count() != 0)
            {
                var readField     = "";
                var joinFieldName = _hostField.Split('.')[1];

                if (NestedData.InData(_hostField, response.data[0]))
                {
                    readField = _hostField;
                }
                else if (NestedData.InData(joinFieldName, response.data[0]))
                {
                    readField = joinFieldName;
                }
                else if (!pkeyIsJoin)
                {
                    throw new Exception(
                              "Join was performed on the field '" + _hostField + "' which was not " +
                              "included in the Editor field list. The join field must be " +
                              "included as a regular field in the Editor instance."
                              );
                }

                // Map the data to the primary key for fast look up
                var join = new Dictionary <string, List <object> >();
                Dictionary <string, object> row;

                while ((row = result.Fetch()) != null)
                {
                    var inner = new Dictionary <string, object>();

                    foreach (var field in _fields.Where(field => field.Apply("get")))
                    {
                        field.Write(inner, row);
                    }

                    var lookup = row["dteditor_pkey"].ToString();
                    if (!join.ContainsKey(lookup))
                    {
                        join.Add(lookup, new List <object>());
                    }

                    join[lookup].Add(inner);
                }

                // Loop over the data and do a join based on the data available
                foreach (var data in response.data)
                {
                    var linkField = pkeyIsJoin
                        ? (data["DT_RowId"].ToString()).Replace(editor.IdPrefix(), "")
                        : NestedData.ReadProp(readField, data).ToString();

                    data.Add(_name, join.ContainsKey(linkField)
                        ? join[linkField]
                        : new List <object>()
                             );
                }
            }

            // Field options
            foreach (var field in _fields)
            {
                var opts = field.OptionsExec(editor.Db());

                if (opts != null)
                {
                    response.options.Add(_name + "[]." + field.Name(), opts);
                }
            }
        }