codesnippets

Code snippets zijn kleine stukjes herbruikbare code die worden gebruikt om specifieke functionaliteit uit te voeren. Het zijn vooraf gedefinieerde codefragmenten die ontwikkelaars kunnen invoegen in hun broncode om bepaalde taken of operaties gemakkelijk en snel uit te voeren, zonder de noodzaak om de code helemaal opnieuw te schrijven.

batchfile

write ('| SCAN RUNBAT | FILE c:/work/run.bat |' )

aanmaak van een bestand conform scan-script ...


BEGIN RUNBAT
  @echo off
  REM    start van de PVM ZorgTTP - exit-waarden  gegenereerd: [[DDMMYYYY]]
  REM    0 De verwerking is succesvol afgerond
  REM    1 De verwerking is afgebroken
  REM    10 Het te verwerken bestand is niet gevonden
  REM    20 Er zijn validatiefouten opgetreden
  set ERRORLEVEL=
  set RETURN_CODE=12

  echo (Before Python script run) ERRORLEVEL VALUE IS: [ %ERRORLEVEL% ] en paramater is  [ %1 ]  en exit-code [ %2% ]
  echo.

  call python -c "import sys; exit_code = 0 ; print('(Inside python script now) Setting up exit code to ' + str(exit_code)); sys.exit(exit_code)"

  echo.
  echo (After Python script run) ERRORLEVEL VALUE IS: [ %ERRORLEVEL% ] en  [ %RETURN_CODE%]
  echo.

  type c:\work\run.bat >> c:\work\run.bat_out

  exit %2% 
RETURN

Aanmaak van een procedure in sqlserver

---------Aanmaak procedure in sqlserver ---------------

CALL CRE_PROC


BEGIN CRE_PROC
 DBEXEC drop procedure GetProductDesc_withparameters 
 QRY
    CREATE PROCEDURE GetProductDesc_withparameters
    (@PID INT)
    AS
    BEGIN
    SET NOCOUNT ON

    insert into grip.grip_para
    ( code, value_char , value_date ) 
      values ( 'test' + str( @PID ) , 'waarde_' + str(@PID) ,  convert(varchar, getdate(), 120) )  
    END;
 EXEC;
RETURN

API_GET

scandate("| VAN 2022-09-01 | TOT 2022-09-10 | CMD CALL VERWERK_API | ")

BEGIN VERWERK_API
  DISP [[SCANDATE]] [[SCANDATE_]]
  DISP Laden van de json van de dag .. [[YYYY-MM-DD]] ,  bestand wordt weggeschreven naar het filesystem.
  DISP json_to_table laadt de data in tabel, middels trunc-vooraf, en verwijdert nadien de json file .
  DISP -- 
#
  api('| DEBUG | DATUM [[SCANDATE]] | URL https://app.planning.nu/grip/api2/ | ENDPOINT attendance-registration/ | PATH ./API_FILES/ | ')
#
  json_to_table ('| DE BUG | SHOW RES | TRUNC ATE | REMOVE | FILE [[SCANDATE]].json  | DIRECTORY C:/Users/grip/PycharmProjects/pythonProject/API_FILES/ | TARGET STG_PLANNINGSDATA | BULK 100 | SLOW |  ')  
#
RETURN

replicatie van een CLOUD-applicatie voor gemeentes

In twee stappen wordt een gehele CLOUD-omgeving opgehaald. in de eerste apiget wordt de tabellen-register overgehaald in een locale stuurtabel. vervolgens wordt vanuit deze stuurtabel vervolg-apigets uitgevoerd waarbij per tabel de inhoud overgehaald en geladen in de STG-tabel. Weinig code voor veel functionaliteit.

CALL CENTRIC_FULL_REFRESH

BEGIN CENTRIC_FULL_REFRESH
 MVAR KEY     = xxxx
 MVAR AUTKEY  = yyyy-Key
 MVAR API_URL = https://dtpklo-grip-apim.azure-api.net/clo/tables 
 #
 # STEP1 : OPHALEN van de lijst met alles wat op te halen is. Deze worden geladen in tabel  CENTRIC_TABELLEN
 # STEP2 : vervolgens wordt PER tabel de json gehaald en geladen in de STG_tabel.
 #
 apiget2 ('| DE BUG | SHOW | ENDPOINT [[API_URL]] | DIRECTORY c:/data/ | KEY [[KEY]] | AUTKEY  [[AUTKEY]] |  ') 
 #
 json_to_table (r'| FILE c:/data/apiget.json | TARGET centric_tabellen2 | DROP  | BULK 100 | ROWS 100 | SLO W | DEBUG | LOWERCASE | ')
 #
 sqlcall (' | SQL select * from grip.centric_tabellen2 order by 1 asc|  CALL GEN_IT   | ROWNUM 6 | DE BUG | ')
 #
RETURN 

BEGIN GEN_IT
  DISP _______________ tabelnaam : [[tablename]]  ________________
  DISP  apiget2 ('| DE BUG | ENDPOINT [[API_URL]] | SOURCE [[tablename]]  | TARGET STG_[[tablename]] | KEY [[KEY]] | AUTKEY  [[AUTKEY]] | TRUNCATE  | DIRE CTORY c:/data/ | ') 
        apiget2 ('| DE BUG | ENDPOINT [[API_URL]] | SOURCE [[tablename]]  | TARGET STG_[[tablename]] | KEY [[KEY]] | AUTKEY  [[AUTKEY]] | TRUNCATE  | DIRE CTORY c:/data/ | ') 
RETURN

mail template

Met onderstaande code kan eenvoudig een HTML-mail samengesteld worden. De tekst van procedure TEMPLATE_ALG wordt als HTML opgenomen in de mail-content en alle HTML-tags kunnen gebruikt worden. Middels de HTMLQRY> kan een sql-query aangeroepen worden en de retour-data wordt als HTML-tabel toegevoegd aan de mail-content. Bevat de sql-query geen records, dan wordt de html-tabel weggelaten. Deze faciliteit wordt onder andere gebruikt voor het versturen van dagelijkse rapportages over het laadproces van de datawarehouses.

mail('| TEMPLATE  TEMPLATE_ALG | SUBJECT Fout opgetreden met FLow | MESSAGE test 123   | FROM dolf@gripopdata.nl | TO  dolf@gripopdata.nl | BIJLAGE c:/data/grip_graph.csv,grip_con.dat,grip.py,grip_flh.py |')

BEGIN TEMPLATE_ALG
  beste datawarehousebeheerder, 

  hieronder enkele overzichten  [[NOW]] ... 

  HTMLQRY> '|  SQL  select * from controle_qr1_v  | HEADER Overzicht van de flows van vandaag en gisteren   | '
  HTMLQRY> '|  SQL  select * from controle_qr2_v  | HEADER Overzicht top-10 trage ETL-processen   | '
  HTMLQRY> '| SSQL  grip_aud                      | HEADER Overzicht laatste 20 ETL-processen   | '
  HTMLQRY> '|  SQL  select * from controle_qr3_v  | HEADER Overzicht errors laatste 7 dagen     | '


   met vriendelijke groet,

   <h4> J.A.G. Jansonius </h4>
RETURN

BEGIN grip_aud 
  select * from grip_aud order by id desc limit 20
RETURN



 mail('| SUBJECT Onderwerp 123 | MESSAGE Testmail 123 | BIJLAGE grip_con.dat,grip.py,grip_flh.py | ')

 mail('| SOURCE grip_aud | SUBJECT Onderwerp 123 | MESSAGE test 123   | FROM dolf@gripopdata.nl | TO  dolf@gripopdata.nl | BIJLAGE grip_con.dat,grip.py,grip_flh.py |')


 csv2mail('| SOURCE select * from xxx.grip_debug  | WHERE 2=2 | SUBJECT  Overzicht debug-gegevens| MESSAGE Bijlage bevat de gegevens van de tabel grip _debug  | DEB UG | SHO WCODE ||')
 csv2mail('| SOURCE  grip_info_v | SUBJECT Scheduler-gegevens | MESSAGE inhoud van de scheduler   | SOURCE_DB postgresql  ||')

ECALL

voorbeeld-1

REPEAT 3 CALL TEST 

BEGIN TEST
   ECALL SLEEP 4 
RETURN

voorbeeld-2

CALL ECALL_DEMO1  

BEGIN ECALL_DEMO1 
  ECALL SLEEP 3
  ECALL SLEEP 3
  ECALL SLEEP 3
  ECALL SLEEP 3
  ECALL SLEEP 3
  ECALL SLEEP 3
RETURN

voorbeeld-3

repeat 2 ECALL CALL ECALL_CALL  

BEGIN ECALL_CALL
  DISP 1234
  sound('x1')
  trunc_insert('| SOURCE grip_aud | TARGET grip_aud_tmp | MAIL | ')
  trunc_insert('| SOURCE grip_aud | TARGET grip_aud_tmp | ')
  trunc_insert('| SOURCE grip_aud | TARGET grip_aud_tmp | ')
RETURN


start_grip.dat

Hieronder de code voor het maken van een batch-file voor starten van GRIP vanuit bv de scheduler.

BEGIN GRIP_BAT
rem  grip.exe -m gui   -f grip_calls
rem  grip.exe -m exec  -l "| COMMAND  SLEEP 10| CONNECTION snowflake |"
rem  grip.exe -m file  -f grip_calls -l PF_HUGO

rem d:
rem cd \GRIP
rem NET USE Q: \\alt.rivm.nl\Data4

copy grip.exe grip_%USERNAME%.exe > NUL 

grip_%USERNAME%.exe  -m gui   -f grip_calls

rem NET USE Q: /DEL

del grip_%USERNAME%.exe > NUL
RETURN

ssvr lineage1


QRY
select 
       CONCAT('"',table_view,'"') as van,
       '->' as x,
       CONCAT('"',details,'"') as naar,
    --object_type, 
    --constraint_type,
    CONCAT('[label="' ,constraint_name,'"]') as FK
from (
       select schema_name(t.schema_id) + '.' + t.[name] as table_view, 
        case when t.[type] = 'U' then 'Table'
            when t.[type] = 'V' then 'View'
            end as [object_type],
        case when c.[type] = 'PK' then 'Primary key'
            when c.[type] = 'UQ' then 'Unique constraint'
            when i.[type] = 1 then 'Unique clustered index'
            when i.type = 2 then 'Unique index'
            end as constraint_type, 
        isnull(c.[name], i.[name]) as constraint_name,
        substring(column_names, 1, len(column_names)-1) as [details]
    from sys.objects t
        left outer join sys.indexes i
            on t.object_id = i.object_id
        left outer join sys.key_constraints c
            on i.object_id = c.parent_object_id 
            and i.index_id = c.unique_index_id
       cross apply (select col.[name] + ', '
                        from sys.index_columns ic
                            inner join sys.columns col
                                on ic.object_id = col.object_id
                                and ic.column_id = col.column_id
                        where ic.object_id = t.object_id
                            and ic.index_id = i.index_id
                                order by col.column_id
                                for xml path ('') ) D (column_names)
    where is_unique = 1
    and t.is_ms_shipped <> 1
    union all 
    select schema_name(fk_tab.schema_id) + '.' + fk_tab.name as foreign_table,
        'Table',
        'Foreign key',
        fk.name as fk_constraint_name,
        schema_name(pk_tab.schema_id) + '.' + pk_tab.name
    from sys.foreign_keys fk
        inner join sys.tables fk_tab
            on fk_tab.object_id = fk.parent_object_id
        inner join sys.tables pk_tab
            on pk_tab.object_id = fk.referenced_object_id
        inner join sys.foreign_key_columns fk_cols
            on fk_cols.constraint_object_id = fk.object_id
    union all
    select schema_name(t.schema_id) + '.' + t.[name],
        'Table',
        'Check constraint',
        con.[name] as constraint_name,
        con.[definition]
    from sys.check_constraints con
        left outer join sys.objects t
            on con.parent_object_id = t.object_id
        left outer join sys.all_columns col
            on con.parent_column_id = col.column_id
            and con.parent_object_id = col.object_id
    union all
    select schema_name(t.schema_id) + '.' + t.[name],
        'Table',
        'Default constraint',
        con.[name],
        col.[name] + ' = ' + con.[definition]
    from sys.default_constraints con
        left outer join sys.objects t
            on con.parent_object_id = t.object_id
        left outer join sys.all_columns col
            on con.parent_column_id = col.column_id
            and con.parent_object_id = col.object_id) a
where constraint_type = 'Foreign key'
order by table_view, constraint_type, constraint_name
SHOW;

LEES_JSON

Wanneer beschikbare functies net even niet doen wat gewenst is, kan eenvoudig een functie toegevoegd worden aan de verzameling.

VAR FILEIN   = c:/data/wester/Notebooks.json 
VAR FILEOUT  = c:/data/wester/Notebooks.csv 
VAR SKIPCOLS = ,_SOURCE_TABLE,meta,

cmd notepad c:/data/wester/Notebooks.csv

runpy('| SCAN LeesJson  |')

csv_to_table( '| TARGET WESTER_H  | SOURCE c:/data/wester/Notebooks.csv  | HEADERLINE 1 |  DROP | DEBU G |  SOU RCE_DB Ora-136 | TARGE T_DB Ora-136 | DELIMITER ; | ENCODING utf-8 | NUMROWS 210 | CHUNKSIZE 1 |  ' )


BEGIN LeesJson
import json
l_comma    = ''   #  
l_header   = ''   #  
l_regel    = ''
l_count    = 0
l_print    = True   #    False : print van tags en types, True is print regels en header. 
l_screen   = False  #    False : geen echo op scherm. 
l_max_rgls = 400
l_file_in  = '[[FILEIN]]'
l_file_out = '[[FILEOUT]]'
l_skipcols = '[[SKIPCOLS]]'

f = open(  l_file_in  ,'r' )
g = open(  l_file_out ,'w' )

list = json.load(f)

for d_element in list  :

    l_count +=1
    l_comma = ''  
    l_regel = ''   

    if l_count > l_max_rgls : break  

    for k,v  in d_element.items():
        if l_skipcols.lower().find( ',' + k.lower() + ',') ==-1:
          if type(v) is list or type(v) is dict or not l_print:
             if l_screen: print (  k, type(v) )
             l_count = l_max_rgls    # maar 1 regel tonen is voldoende
          else:   
             if l_count == 1:
                 l_header =  l_header + l_comma + '"' + str(k) + '"'    # bouw de header op

             l_regel = l_regel + l_comma + '"' + str(v) + '"'      # bouw de regel op
             l_comma = ';'

    if l_print:
        if  l_count == 1:
           if l_screen : print(  'Header', l_header + chr(13)  )
           g.write ( l_header + chr(13) )

        if l_screen: print ( 'Regel', l_count , l_regel   )
        g.write ( l_regel + chr(13) )    

print ( str( l_count ) + ' regels gelezen/geschreven .. ')   
f.close()
g.close()

RETURN

cx_oracle


runpy('| SCAN TRY |')

BEGIN TRY
import cx_Oracle

l_insert_into = 'insert into pygrip.centric_tabellen ( ATTENDANCEREGISTRATIONID, EMPLOYEEID, PERSONNELNUMBER, DATETIME, EVENT, SERIALNUMBER, DEVICENAME) VALUES ( :s, :s, :s, :s, :s, :s, :s) '
l_bucket = [ ( 477499, 2481, 1001568, '2022-09-01T00:00:04+02:00', 'clocked out', 6136185160068, 'GRIP 4' )
           , ( 477499, 2481, 1001568, '2022-09-01T00:00:04+02:00', 'clocked out', 6136185160068, 'GRIP 4' )
           , ( 477499, 2481, 1001568, '2022-09-01T00:00:04+02:00', 'clocked out', 6136185160068, 'GRIP 4' ) ]

print ( type(l_bucket), l_bucket)  
connection = cx_Oracle.connect(user="pygrip", password="gripopdata", dsn="gripop/ora11g",  encoding="UTF-8")
cursor = connection.cursor()
cursor.executemany(l_insert_into, l_bucket )
connection.commit()
RETURN

start_grip_job.bat

Voor het starten van een GRIP-proces kan onderstaande batch-file gebruikt worden. Zo kan bv vanuit de scheduler van windows een FLOW, LABEL of een Commando gestart worden. Let daarbij op dat je de juiste connectie opgeeft welke in de grip_con.dat voorkomt en geactiveerd wordt . De FLOW wordt nl in de juiste database-connectie gezocht, terwijl veel commano's loggen in de database waardoor er altijd een database bekend moet zijn.

kopieer onderstaande in uw start_grip_job.bat en pas hem zondanig aan op uw omgeving.

rem  grip.exe -m gui   -f grip_calls
rem  grip.exe -m exec  -l "| COMMAND  SLEEP 10| CONNECTION snowflake |"
rem  grip.exe -m file  -f grip_calls -l PF_HUGO

echo off

c:
cd \C:\Users\dolf\PycharmProjects\pythonProject

rem grip.exe -m exec  -l "| COMMAND  flow_run('| FLOW PF_JAGGG |') | CONNECTION Ora-136 |"
rem grip.exe -m exec  -l "| COMMAND  flow_run('| FLOW PF_JAGGER |') | CONNECTION pg_duitsland  |"
rem grip.exe -m exec  -l "| COMMAND  flow_run('| FLOW Mainflow_stagen_Neoforcedata_notebooks |')  | CONNECTION GW_grip |"

NET USE Q: \\alt.rivm.nl\Data4      2>nul

copy grip.exe grip_%USERNAME%.exe   2>nul

setlocal enabledelayedexpansion   

set "p1=%~1"
set "p1=!p1:"=!"

set "p2=%~2"
set "p2=!p2:"=!"

set "p3=%~3"
set "p3=!p3:"=!"

echo  ( !p1!) ( !p2! )  ( !p3! )  
echo
echo  start_grip_job.bat 'FLOW'  'FLOW-naam' 'Connection-naam'  ,  voorbeeld: start_grip_job.bat  FLOW PF_BATCH  pg_duitsland 
echo  start_grip_job.bat 'CMD'   'grp-script-naam' 'label'      ,  voorbeeld: start_grip_job.bat  CMD   "SLEEP 10"  pg_duitsland
echo  start_grip_job.bat 'LABEL' 'grp-script-naam' 'label'      ,  voorbeeld: start_grip_job.bat  LABEL MyProc  grip_calls  
echo ----------------


if  %1 equ FLOW   goto FLOW
if  %1 equ CMD    goto CMD
if  %1 equ LABEL  goto LABEL
if  %1 equ HELP   goto end

echo ---------------
echo Geen juiste parameters meegegeven ... 
echo ----------------
goto end

:FLOW 
echo Start van de flow : grip.exe -m exec  -l "| COMMAND   flow_run('| FLOW  %2 |')  | CONNECTION %3 |"

  grip_%USERNAME%.exe -m exec  -l "| COMMAND  flow_run('| FLOW  %2 |')  | CONNECTION %3 |"

goto end

:CMD
 echo Start van het commando  : grip.exe -m file  -f %2 -l %3 

  grip_%USERNAME%.exe -m exec -l "| COMMAND  %2 | CONNECTION %3 |"

goto end

:LABEL
 echo Start van aanroep procedure in script  : grip.exe -m file  -f %3 -l %2 

  grip_%USERNAME%.exe -m file  -f %3 -l %2 

goto end



:end 


RID_DELETE FYSIEK

Middels rid_delete() kun je records 'administratief' verwijderen. de DATE_UPDATED en DATE_DELETED krijgt de datum van het moment en CURR_ID krijgt de waarde 'N'

Met parameter NO_UPDUPD wordt DATE_UPDATED niet geset .

hieronder een stukje code voor experimenteren, voor sqlserver.


#STAP1 : aanmaak test-tabel 
trunc_insert( '| SOURCE grip_metadata_v | TARGET rid_delete_table  | LOG_INFO demo delete |' )

DBEXEC drop  view rid_delete_table_rd_v
QRY
create view rid_delete_table_rd_v
as
select %%physloc%% RID, a.*
from xxx.rid_delete_table a 
where table_name = 'GRIP_LOG'
and curr_id = 'Y'
EXEC;

#STAP2 : administratief verwijderen , dus niet fysiek, en met CURR_ID = 'N'. raadpleeg de gegenererde code en zie het verschil 
rid_delete( '| SOURCE rid_delete_table_rd_v | TARGET rid_delete_table | LOG_INFO administratief verwijderen van ... | SHOWRES| SHOWCODE | ')
rid_delete( '| SOURCE rid_delete_table_rd_v | TARGET rid_delete_table | LOG_INFO update_date niet geset         ... | SHOWRES| SHOWCODE | NO_UPDUPD| ')

select * from xxx.rid_delete_table where table_name = 'GRIP_LOG'


DBEXEC drop  view rid_delete_table_rdf_v
QRY
create view rid_delete_table_rdf_v
as
select %%physloc%% RID, a.*  from xxx.rid_delete_table a
where curr_id = 'N'
EXEC;

#STAP3 : hier worden de records werkelijk verwijderd. Wat de view selecteert, wordt verwijderd !
rid_delete_fysiek( '| SOURCE rid_delete_table_rdf_v | TARGET rid_delete_table | LOG_INFO records worden nu fysiek verwijderd . ... | SHOWRES | SHOWCODE |')

select * from xxx.rid_delete_table where table_name = 'GRIP_LOG'