@@ -133,15 +133,23 @@ std::shared_ptr<ASTSettingsProfileElements> SettingsProfileElements::toAST() con
133133{
134134 auto res = std::make_shared<ASTSettingsProfileElements>();
135135 for (const auto & element : *this )
136- res->elements .push_back (element.toAST ());
136+ {
137+ auto element_ast = element.toAST ();
138+ if (!element_ast->empty ())
139+ res->elements .push_back (element_ast);
140+ }
137141 return res;
138142}
139143
140144std::shared_ptr<ASTSettingsProfileElements> SettingsProfileElements::toASTWithNames (const AccessControl & access_control) const
141145{
142146 auto res = std::make_shared<ASTSettingsProfileElements>();
143147 for (const auto & element : *this )
144- res->elements .push_back (element.toASTWithNames (access_control));
148+ {
149+ auto element_ast = element.toASTWithNames (access_control);
150+ if (!element_ast->empty ())
151+ res->elements .push_back (element_ast);
152+ }
145153 return res;
146154}
147155
@@ -252,4 +260,185 @@ bool SettingsProfileElements::isAllowBackupSetting(const String & setting_name)
252260 return Settings::Traits::resolveName (setting_name) == ALLOW_BACKUP_SETTING_NAME;
253261}
254262
263+
264+ AlterSettingsProfileElements::AlterSettingsProfileElements (const SettingsProfileElements & ast)
265+ {
266+ drop_all_settings = true ;
267+ drop_all_profiles = true ;
268+ add_settings = ast;
269+ }
270+
271+ AlterSettingsProfileElements::AlterSettingsProfileElements (const ASTSettingsProfileElements & ast)
272+ : AlterSettingsProfileElements(SettingsProfileElements{ast})
273+ {
274+ }
275+
276+ AlterSettingsProfileElements::AlterSettingsProfileElements (const ASTSettingsProfileElements & ast, const AccessControl & access_control)
277+ : AlterSettingsProfileElements(SettingsProfileElements{ast, access_control})
278+ {
279+ }
280+
281+ AlterSettingsProfileElements::AlterSettingsProfileElements (const ASTAlterSettingsProfileElements & ast)
282+ {
283+ drop_all_settings = ast.drop_all_settings ;
284+ drop_all_profiles = ast.drop_all_profiles ;
285+
286+ if (ast.add_settings )
287+ add_settings = SettingsProfileElements{*ast.add_settings };
288+
289+ if (ast.modify_settings )
290+ modify_settings = SettingsProfileElements{*ast.modify_settings };
291+
292+ if (ast.drop_settings )
293+ drop_settings = SettingsProfileElements{*ast.drop_settings };
294+ }
295+
296+ AlterSettingsProfileElements::AlterSettingsProfileElements (const ASTAlterSettingsProfileElements & ast, const AccessControl & access_control)
297+ {
298+ drop_all_settings = ast.drop_all_settings ;
299+ drop_all_profiles = ast.drop_all_profiles ;
300+
301+ if (ast.add_settings )
302+ add_settings = SettingsProfileElements{*ast.add_settings , access_control};
303+
304+ if (ast.modify_settings )
305+ modify_settings = SettingsProfileElements{*ast.modify_settings , access_control};
306+
307+ if (ast.drop_settings )
308+ drop_settings = SettingsProfileElements{*ast.drop_settings , access_control};
309+ }
310+
311+ void SettingsProfileElements::applyChanges (const AlterSettingsProfileElements & changes)
312+ {
313+ // / 1. First drop profiles and settings which should be dropped.
314+ if (changes.drop_all_profiles )
315+ {
316+ for (auto & element : *this )
317+ element.parent_profile .reset (); // / This makes the element empty if it's a "profile" element.
318+ }
319+
320+ if (changes.drop_all_settings )
321+ {
322+ for (auto & element : *this )
323+ {
324+ // / This makes the element empty if it's a "setting" element.
325+ // / Empty elements will be removed later at the end of this function.
326+ element.setting_name .clear ();
327+ element.value .reset ();
328+ element.min_value .reset ();
329+ element.max_value .reset ();
330+ element.writability .reset ();
331+ }
332+ }
333+
334+ auto apply_drop_profile = [&](const UUID & profile_id)
335+ {
336+ for (auto & element : *this )
337+ {
338+ if (element.parent_profile == profile_id)
339+ element.parent_profile .reset (); // / This makes the element empty if it corresponds to that profile.
340+ }
341+ };
342+
343+ auto apply_drop_setting = [&](const String & setting_name, size_t end_index = -1 )
344+ {
345+ if (end_index == static_cast <size_t >(-1 ))
346+ end_index = this ->size ();
347+ for (size_t i = 0 ; i != end_index; ++i)
348+ {
349+ auto & element = (*this )[i];
350+ if (element.setting_name == setting_name)
351+ {
352+ // / This makes the element empty if it corresponds to that setting.
353+ // / Empty elements will be removed later at the end of this function.
354+ element.setting_name .clear ();
355+ element.value .reset ();
356+ element.min_value .reset ();
357+ element.max_value .reset ();
358+ element.writability .reset ();
359+ }
360+ }
361+ };
362+
363+ for (const auto & drop : changes.drop_settings )
364+ {
365+ if (drop.parent_profile )
366+ apply_drop_profile (*drop.parent_profile );
367+ if (!drop.setting_name .empty ())
368+ apply_drop_setting (drop.setting_name );
369+ }
370+
371+ // / 2. Then add profiles which should be added.
372+ auto apply_add_profile = [&](const UUID & profile_id, bool check_if_exists = true )
373+ {
374+ if (check_if_exists)
375+ apply_drop_profile (profile_id);
376+ SettingsProfileElement new_element;
377+ new_element.parent_profile = profile_id;
378+ push_back (new_element);
379+ };
380+
381+ for (const auto & add : changes.add_settings )
382+ {
383+ if (add.parent_profile )
384+ apply_add_profile (*add.parent_profile );
385+ }
386+
387+ // / 3. Then add settings which should be added.
388+ auto apply_add_setting = [&](const SettingsProfileElement & add, bool check_if_exists = true )
389+ {
390+ if (check_if_exists)
391+ apply_drop_setting (add.setting_name );
392+ SettingsProfileElement new_element;
393+ new_element.setting_name = add.setting_name ;
394+ new_element.value = add.value ;
395+ new_element.min_value = add.min_value ;
396+ new_element.max_value = add.max_value ;
397+ new_element.writability = add.writability ;
398+ push_back (new_element);
399+ };
400+
401+ for (const auto & add : changes.add_settings )
402+ {
403+ if (!add.setting_name .empty ())
404+ apply_add_setting (add);
405+ }
406+
407+ // / 4. After that modify settings which should be modified.
408+ auto apply_modify_setting = [&](const SettingsProfileElement & modify, bool check_if_exists = true )
409+ {
410+ if (check_if_exists && !this ->empty ())
411+ {
412+ for (int i = static_cast <int >(this ->size ()) - 1 ; i >= 0 ; --i)
413+ {
414+ auto & element = (*this )[i];
415+ if (element.setting_name == modify.setting_name )
416+ {
417+ if (modify.value )
418+ element.value = modify.value ;
419+ if (modify.min_value )
420+ element.min_value = modify.min_value ;
421+ if (modify.max_value )
422+ element.max_value = modify.max_value ;
423+ if (modify.writability )
424+ element.writability = modify.writability ;
425+ apply_drop_setting (modify.setting_name , i);
426+ return ;
427+ }
428+ }
429+ }
430+ apply_add_setting (modify, /* check_if_exists= */ false );
431+ };
432+
433+ for (const auto & modify : changes.modify_settings )
434+ {
435+ chassert (!modify.parent_profile ); // / There is no such thing as "MODIFY PROFILE".
436+ if (!modify.setting_name .empty ())
437+ apply_modify_setting (modify);
438+ }
439+
440+ // / 5. Finally remove empty elements from the result list of elements.
441+ std::erase_if (*this , [](const SettingsProfileElement & element) { return element.empty (); });
442+ }
443+
255444}
0 commit comments