Небольшой пятничный кек. Коллеги поделились кулстори. Есть некая система, которая ходит к этим самым коллегам по HTTP и периодически присылает кривые жсоны. Например:
{
"id": 123123,
"name": ,
"attr": false
}То кавычки забудут, то ещё чего.
Как такое возможно, спросите вы? А всё потому, что этот жсон формируется огромным 30-этажным SQL-запросом из coalesce и конкатенаций. Что-то типа:
-- job security 99lvl, LLM себя из розетки выключит увидев такое
SELECT concat('{','"id":',t.id,',','"name":"',coalesce(coalesce(u.name,(select name from users where id=t.user_id and rownum=1)),' '),'",','"attr":',case when row_number() over (partition by t.user_id order by t.created_at) = 1 then lower(cast(t.attr as varchar(10))) else lower(cast(t.attr as varchar(10))) end,',','"settings":{','"lang":"',coalesce(u.lang,(select lang from user_prefs where user_id=t.user_id and rownum=1),'ru'),'",','"theme":',case when u.theme is null then 'null' when u.theme=1 then '"light"' when u.theme=2 then '"dark"' else concat('"',u.theme,'"') end,',','"notifications":',coalesce(cast(u.notif as varchar),(select cast(prefs as varchar) from user_prefs where user_id=t.user_id and rownum=1),'false'),'},','"roles":',(select concat('[',string_agg(concat('"',r.role_name,'"'),','),']') from user_roles r where r.user_id=u.id group by r.user_id),',','"history":{','"prev_name":"',lag(u.name) over (partition by t.user_id order by t.created_at desc),'",','"next_name":"',lead(u.name) over (partition by t.user_id order by t.created_at desc),'"},','"recursive_check":',case when t.id=(select max(id) from requests where user_id=t.user_id) then concat('"FINALLY_',t.id,'"') else concat('"NOT_FINALLY_',(select concat('SUB_',t2.id) from requests t2 where t2.user_id=t.user_id and rownum=1),'"') end,case when exists(select 1 from dual where t.id>0) then ',' else '' end,'}','}') as json_response FROM requests t left join users u on t.user_id=u.id where t.status='active' and row_number() over (order by t.created_at)>0 order by t.created_at desc
Я даже не знаю, как это комментировать и сколько SQL-инъекций с прочими уязвимостями сидит в такой конструкции. Зато теперь понятно, почему на просьбу добавить новое поле они реагируют так нервно.
В общем, отдать JSON прямо из базы можно через какой-нибудь json_agg, но не напрямую же (наверное, это будет недостаточно энтерпрайзно, да и админа БД просто так, что ли, нанимали?)