depo_snapshot.go: объекты FTV_M2M*/bj* (тип, даты создания/изменения,
хеш текста, если доступен), столбцы и строки таблиц, счётчики по STATE,
зависимости поставки Fancy, константы процедур, задания SQL Agent, права
логина bj. Данных клиентов нет. Раз в сутки и по кнопке в «Статусе
системы» (GET /admin/status/depo-snapshot), история в
/var/lib/bj/.bj/depo-snapshots — сравнить установки (28 и 9) и увидеть
ручные правки в DEPO.
«Сервер: HTTPS» — поле «Доменное имя сервера bj» (было только в мастере).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
iferr:=db.QueryRowContext(ctx,`SELECT DB_NAME(), CAST(SERVERPROPERTY('ProductVersion') AS nvarchar(64)), CAST(DATABASEPROPERTYEX(DB_NAME(),'Collation') AS nvarchar(128)), SUSER_SNAME()`).
cr,err:=db.QueryContext(ctx,`SELECT c.name, t.name, c.max_length, c.is_nullable FROM sys.columns c JOIN sys.types t ON t.user_type_id=c.user_type_id
WHERE c.object_id=OBJECT_ID(@t) ORDER BY c.column_id`,sql.Named("t","dbo."+o.Name))
iferr==nil{
forcr.Next(){
varn,tstring
varmlint
varnullbool
ifcr.Scan(&n,&t,&ml,&null)==nil{
col:=fmt.Sprintf("%s %s(%d)",n,t,ml)
if!null{
col+=" NOT NULL"
}
o.Columns=append(o.Columns,col)
}
}
cr.Close()
}
_=db.QueryRowContext(ctx,`SELECT SUM(p.rows) FROM sys.partitions p WHERE p.object_id=OBJECT_ID(@t) AND p.index_id IN (0,1)`,sql.Named("t","dbo."+o.Name)).Scan(&o.Rows)
hasState:=false
for_,c:=rangeo.Columns{
ifstrings.HasPrefix(c,"STATE "){
hasState=true
}
}
ifhasState{
sr,err:=db.QueryContext(ctx,`SELECT ISNULL(CAST(STATE AS nvarchar(40)),'NULL'), COUNT(*) FROM dbo.[`+o.Name+`] GROUP BY STATE ORDER BY 1`)
iferr==nil{
varparts[]string
forsr.Next(){
varststring
varnint64
ifsr.Scan(&st,&n)==nil{
parts=append(parts,fmt.Sprintf("%s:%d",st,n))
}
}
sr.Close()
s.States[o.Name]=strings.Join(parts," ")
}
}
}
for_,d:=rangedepoSnapDeps{
varnint
_=db.QueryRowContext(ctx,`SELECT COUNT(*) FROM sys.objects WHERE name=@n`,sql.Named("n",d)).Scan(&n)
s.Deps[d]=n>0
}
ifsr,err:=db.QueryContext(ctx,`IF OBJECT_ID('dbo.FTV_M2M_SETTINGS') IS NOT NULL SELECT * FROM dbo.FTV_M2M_SETTINGS`);err==nil{
cols,_:=sr.Columns()
forsr.Next(){
vals:=make([]sql.NullString,len(cols))
ptr:=make([]any,len(cols))
fori:=rangevals{
ptr[i]=&vals[i]
}
ifsr.Scan(ptr...)==nil{
row:=map[string]any{}
fori,c:=rangecols{
ifvals[i].Valid{
row[c]=vals[i].String
}
}
s.Settings=append(s.Settings,row)
}
}
sr.Close()
}
// задания SQL Agent: шаги — из sysjobs/sysjobsteps; расписание — отдельно (sysschedules часто закрыт)
jr,err:=db.QueryContext(ctx,`SELECT j.name, j.enabled, ISNULL(st.step_name,''), ISNULL(st.database_name,''), ISNULL(st.command,''), CAST(j.job_id AS nvarchar(40))
FROM msdb.dbo.sysjobs j LEFT JOIN msdb.dbo.sysjobsteps st ON st.job_id=j.job_id
WHERE j.name LIKE '%bj%' OR st.command LIKE '%FTV[_]M2M%' ORDER BY j.name, st.step_id`)
iferr:=db.QueryRowContext(ctx,`SELECT TOP 1 CONCAT('freq_type=',sc.freq_type,' subday=',sc.freq_subday_type,'/',sc.freq_subday_interval,' enabled=',sc.enabled)
FROM msdb.dbo.sysjobschedules js JOIN msdb.dbo.sysschedules sc ON sc.schedule_id=js.schedule_id WHERE CAST(js.job_id AS nvarchar(40))=@id`,sql.Named("id",ids[n])).Scan(&sched);err==nil{
byName[n].Schedule=sched
}
s.Jobs=append(s.Jobs,*byName[n])
}
}
noDef:=0
for_,o:=ranges.Objects{
ifo.Type!="USER_TABLE"&&o.DefHash==""{
noDef++
}
}
ifnoDef>0{
s.Errors=append(s.Errors,fmt.Sprintf("тексты %d процедур недоступны логину bj (нет VIEW DEFINITION) — изменения видны по дате modified",noDef))
<labelstyle="display:flex;align-items:center;gap:8px;font-weight:400"><inputtype="checkbox"name="redirect"style="width:auto"{{if.Settings.HTTPS.RedirectOn}}checked{{end}}><b>Открывать bj только по HTTPS</b> — браузер с http:// перенаправляется на https://</label>
<pclass="muted"style="font-size:12.5px;margin:4px 0 0">bj впишет имя в свой сертификат — интерфейс будет открываться по нему без предупреждения о несовпадении имени. DNS-запись заводит администратор сети.</p>
<pclass="muted">Снимок объектов bj в базе DEPO: трансферные таблицы и процедуры FTV_M2M* (даты изменения), зависимости поставки Fancy, права логина bj, счётчики по статусам. Данных клиентов в снимке нет. bj снимает его раз в сутки и хранит историю — по ней видно, что и когда меняли в DEPO.</p>
<aclass="btn"href="/admin/status/depo-snapshot"target="_blank"rel="noopener">Снять снимок сейчас (JSON)</a>
</div>
{{if devOn}}{{/* дорожная карта разработки — только в режиме разработки */}}
<divclass="card">
<h2>Что подключается на следующих этапах</h2>
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.