#from __future__ import annotations from typing import List from sqlalchemy import BOOLEAN, Column,INTEGER,NVARCHAR, ForeignKey,Select, and_, or_,DateTime,text,VARCHAR from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER, TINYINT from sqlalchemy.orm import relationship,Session,Mapped,mapped_column,contains_eager from sqlalchemy.ext.declarative import declarative_base from datetime import datetime,timedelta,time import json from json import JSONEncoder #import sysjobhistory import inn class MyEncoder(JSONEncoder): def default(self, obj): if(isinstance(obj,Sysjobs) or isinstance(obj,Sysjobhistory)): return obj.getDict() else: return object.__dict__ Base = declarative_base() class Sysjobs(Base): __tablename__ = "sysjobs" job_id: Mapped[str] = mapped_column(UNIQUEIDENTIFIER,primary_key=True) name=Column(NVARCHAR(128)) enabled=Column(TINYINT) sysjobhistories: Mapped[List["Sysjobhistory"]] = relationship(back_populates="sysjob") dataflow_jobs: Mapped[List["DataflowManagement_JobListe"]] = relationship(back_populates="sysjob") sysjobsteps: Mapped[List["msdb_sysjobsteps"]] = relationship(back_populates="sysjob") parents: Mapped[List["DataflowManagement_JobAfhaengighed"]] =relationship(back_populates="child", foreign_keys="DataflowManagement_JobAfhaengighed.ChildJobID") children: Mapped[List["DataflowManagement_JobAfhaengighed"]] = relationship(back_populates="parent", foreign_keys="DataflowManagement_JobAfhaengighed.ParentJobID") def __iter__(self): yield from { "job_id": self.job_id, "name": self.name }.items() def __iter__(self): yield from { "job_id": str(self.job_id), "name": self.name }.items() def __str__(self): return json.dumps(self.getDict()) def getDict(self): return {'job_id': str(self.job_id), 'name': self.name} def __repr__(self): return self.__str__() def getTest(self,session: Session): stmt = Select(Sysjobs).join(Sysjobhistory).where(Sysjobhistory.run_date>20230601).distinct() print(stmt) with Session(engine) as session: row : Sysjobs res = session.execute(stmt).all() for row in res: print(row.Sysjobs.name + ' ' + str(row.Sysjobhistory.run_date) + ' ' + str(row.Sysjobhistory.run_time)) def getMedianDag(self,stepID: int,antalDage: int,ugeDag: int=0): session=Session.object_session(self) sqlStr='''DECLARE @dage int = :antalDage DECLARE @job VARCHAR(200) = :selfName DECLARE @ugeDag INT = :ugeDag DECLARE @stepID INT = :stepID ;WITH ctedateconversion AS( SELECT PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY run_datetime) OVER() AS MedianRun_datetime , [t].[run_datetime] , PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY [t].[run_duration]) OVER() AS run_duration FROM ( SELECT job_name, run_datetime, run_duration from ( SELECT TOP (@dage) j.name as job_name, run_datetime = CONVERT(DATETIME, '1970-01-01') + (run_time * 9 + run_time % 10000 * 6 + run_time % 100 * 10) / 216e4, run_duration = (run_duration/10000*3600 + (run_duration/100)%100*60 + run_duration%100) from msdb..sysjobhistory h inner join msdb..sysjobs j ON h.job_id = j.job_id WHERE [j].[name] LIKE @job AND [h].[step_id]=@stepID ''' if(ugeDag!=0): sqlStr+=''' AND DATEPART(WEEKDAY,CONVERT(DATETIME, RTRIM(run_date)) + (run_time * 9 + run_time % 10000 * 6 + run_time % 100 * 10) / 216e4)=@ugeDag --1 = mandag ''' sqlStr+=''' ORDER BY [h].[run_date] DESC ) t ) t ) SELECT [ctedateconversion].[MedianRun_datetime] AS MedianRun_datetime_SpecificDate,DATEADD(SECOND,[ctedateconversion].[run_duration],[ctedateconversion].[MedianRun_datetime]) FROM [ctedateconversion] WHERE [ctedateconversion].[MedianRun_datetime] = [ctedateconversion].[run_datetime] GROUP BY [ctedateconversion].[MedianRun_datetime], [ctedateconversion].[run_duration]''' stmt=text(sqlStr).params(antalDage=antalDage,selfName=self.name,ugeDag=ugeDag,stepID=stepID) res=session.execute(stmt).all() resResult=[] if(len(res)>0): resResult=list(res[0]) if(resResult[0]0): resReturn+=',' resReturn+=parent.parent.name return resReturn def getNattensKoersel(session) -> List['Sysjobs']: natStat=(datetime.today()-timedelta(days=1)).replace(hour=20,minute=0,second=0,microsecond=0) resReturn: List['Sysjobs'] = list() stmt = Select(Sysjobs).join(DataflowManagement_JobListe).join(Sysjobhistory).join(DataflowManagement_JobsForExecution).where(Sysjobhistory.step_id==0).where(DataflowManagement_JobListe.Aktiv==1).where(or_(and_(Sysjobhistory.run_date>=int((natStat.strftime('%Y%m%d'))),(Sysjobhistory.run_time>=int((natStat.strftime('%H%M%S'))))),Sysjobhistory.run_date>=int((datetime.today().strftime('%Y%m%d'))))).distinct() row : Sysjobs stmt.options(contains_eager(Sysjobs.sysjobhistories), contains_eager(Sysjobs.parents), contains_eager(DataflowManagement_JobAfhaengighed.parent)) res = session.execute(stmt).all() return res def getSysjob(session, sysjobName: str, fullName:bool=True,historikDage: int=0): resReturn=None natStat=(datetime.today()-timedelta(days=historikDage)).replace(hour=20,minute=0,second=0,microsecond=0) if(sysjobName!=None): stmt=Select(Sysjobs) if(historikDage>0): stmt=stmt.join(Sysjobhistory).where(or_(and_(Sysjobhistory.run_date>=int((natStat.strftime('%Y%m%d'))),(Sysjobhistory.run_time>=int((natStat.strftime('%H%M%S'))))),Sysjobhistory.run_date>=int((datetime.today().strftime('%Y%m%d'))))) if(fullName==False): stmt = stmt.where(Sysjobs.name.like(sysjobName)) else: stmt = stmt.where(Sysjobs.name==sysjobName) if(historikDage>0): stmt=stmt.options(contains_eager(Sysjobs.sysjobhistories)) try: resReturn=session.execute(stmt).unique().all() except: session.rollback() return resReturn def getSmallestWaitOfParent(self): return class Sysjobhistory(Base): __tablename__ = "sysjobhistory" instance_id=Column(INTEGER,primary_key=True) job_id: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id")) step_id = Column(INTEGER) step_name=Column(NVARCHAR(128)) run_date=Column(INTEGER) run_time=Column(INTEGER) run_duration=Column(INTEGER) sysjob: Mapped["Sysjobs"] = relationship(back_populates="sysjobhistories") def __iter__(self): yield from { "instance_id": self.instance_id, "job_id": str(self.job_id), "step_id": self.step_id, "step_name": self.step_name, "getStartTime": str(self.getStartTime()), "getEndTime": str(self.getEndTime()) }.items() def __str__(self): return json.dumps(self.getDict()) def getDict(self): return {'instance_id': self.instance_id, 'job_id': str(self.job_id), 'step_id' : self.step_id, 'step_name': self.step_name, 'getStartTime': str(self.getStartTime()), 'getEndTime': str(self.getEndTime())} def __repr__(self): return self.__str__() def getTest(self): engine=inn.getEngine("msdb") # stmt = Select(Sysjobhistory) # with Session(engine) as session: # for row in session.execute(stmt).first(): # print(row) def getStartTime(self) -> datetime: resReturn: datetime resReturn = datetime.fromisoformat(str(self.run_date)[0:4]+'-'+ str(self.run_date)[4:6]+'-'+str(self.run_date)[6:8]+' '+str(1000000+self.run_time)[1:3]+':'+str(1000000+self.run_time)[3:5]+':'+str(1000000+self.run_time)[5:7]) return resReturn def getEndTime(self) -> datetime: resReturn: datetime resReturn = self.getStartTime()+timedelta(seconds=self.getRunDurationInSec()) return resReturn def getRunDurationInSec(self) -> int: resReturn: int resReturn = 3600*(int(str(self.run_duration+1000000)[1:3]))+60*(int(str(self.run_duration+1000000)[3:5]))+(int(str(self.run_duration+1000000)[3:5])) return resReturn def getRunDurationInHourMinSec(self) -> str: resReturn: str resReturn=str(timedelta(seconds=self.getRunDurationInSec())) return resReturn def getRunHistory(self,Sysjob): engine=inn.getEngine("msdb") stmt = Select(Sysjobhistory).join(Sysjobhistory).filter(Sysjob) with Session(engine) as session: row : Sysjobs res = session.execute(stmt).all() print(res.__len__) class DataflowManagement_JobListe(Base): __tablename__ = "JobListe" __table_args__ = { "schema": "dataflowmanagement.flw" } JobID: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"),primary_key=True) Aktiv=Column(BOOLEAN) sysjob: Mapped["Sysjobs"] = relationship(back_populates="dataflow_jobs") class DataflowManagement_JobAfhaengighed(Base): __tablename__ = "JobAfhaengighed" __table_args__ = { "schema": "dataflowmanagement.flw" } ParentJobID: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"), primary_key=True) ChildJobID: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"), primary_key=True) OprettetDato: Mapped[datetime] = Column(DateTime) AendretDato: Mapped[datetime] = Column(DateTime) parent: Mapped[List["Sysjobs"]] = relationship(back_populates="parents",foreign_keys=[ParentJobID]) child: Mapped[List["Sysjobs"]] = relationship(back_populates="children",foreign_keys=[ChildJobID]) class DataflowManagement_JobMasterSetup(Base): __tablename__ = "JobMasterSetup" __table_args__ = { "schema": "dataflowmanagement.flw" } JobID: Mapped[str] = mapped_column(UNIQUEIDENTIFIER,primary_key=True) CurrentBatchID: Mapped[int] = mapped_column(INTEGER) MinMellemAfvikling: Mapped[int] = mapped_column(INTEGER) def getCurrentBatchId(session): stmt = Select(DataflowManagement_JobMasterSetup) res = session.execute(stmt).all() return res class DataflowManagement_JobsForExecution(Base): __tablename__ = "JobsForExecution" __table_args__ = { "schema": "dataflowmanagement.flw" } JobID: Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"),primary_key=True) BatchID: Mapped[int] = mapped_column(INTEGER) ExecutionID: Mapped[int] = mapped_column(primary_key=True) class msdb_sysjobsteps(Base): __tablename__ = "sysjobsteps" __table_args__ = { "schema": "msdb.dbo" } job_id:Mapped[str] = mapped_column(ForeignKey("sysjobs.job_id"),primary_key=True) step_id: Mapped[int] = mapped_column(INTEGER,primary_key=True) step_uid: Mapped[str] = mapped_column(UNIQUEIDENTIFIER) command:Mapped[str] = mapped_column(NVARCHAR) sysjob: Mapped["Sysjobs"] = relationship(back_populates="sysjobsteps") #class AllExecutionMessages(Base):