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'