Rozšiřování a upravování stávající funkcionality PLToolbox, Orafce

Podobné dokumenty
PostgreSQL. Podpora dědičnosti Rozšiřitelnost vlastní datové typy. Univerzální nasazení ve vědecké sféře

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

IUJCE 07/08 Přednáška č. 6

IUJCE Přednáška č. 11. další prvky globální proměnné, řízení viditelnosti proměnných, funkcí

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

PREPROCESOR POKRAČOVÁNÍ

Zápis programu v jazyce C#

int ii char [16] double dd název adresa / proměnná N = nevyužito xxx xxx xxx N xxx xxx N xxx N

První kapitola úvod do problematiky

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

Programování v C++ 1, 1. cvičení

SQL injection princip a ochrana

PL/SQL. Jazyk SQL je jazykem deklarativním, který neobsahuje procedurální příkazy jako jsou cykly, podmínky, procedury, funkce, atd.

IUJCE 07/08 Přednáška č. 1

ZPRO v "C" Ing. Vít Hanousek. verze 0.3

Preprocesor. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016

Programovací jazyk C++ Hodina 1

Algoritmizace a programování

David Bednárek Jakub Yaghob Filip Zavoral.

Aplikace Embedded systémů v Mechatronice. Michal Bastl A2/713a

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE LEXIKÁLNÍ ANALÝZA

int => unsigned int => long => unsigned long => float => double => long double - tj. bude-li:

Logické operace. Datový typ bool. Relační operátory. Logické operátory. IAJCE Přednáška č. 3. může nabýt hodnot: o true o false

PB161 Programování v jazyce C++ Přednáška 10

Strukturované typy a ukazatele. Úvod do programování 1 Tomáš Kühr

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Generické programování

Výrazy, operace, příkazy

PŘETĚŽOVÁNÍ OPERÁTORŮ

Jazyk C++ I. Šablony

Úvod do programovacích jazyků (Java)

Opakování programování

Operační systémy. Cvičení 4: Programování v C pod Unixem

Jazyk C++ I. Šablony 2

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Jazyk C# a platforma.net

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) 28. prosince Fakulta elektrotechniky a informatiky Katedra softwarových technologií

přetížení operátorů (o)

Implementace funkce XMLTABLE v PostgreSQL. Pavel

Základy C++ I. Jan Hnilica Počítačové modelování 18

K8055D.DLL v Technická příručka. Úvod. Obecné. Konvence volání. Nastavení adresy karty

Databázové systémy. Dotazovací jazyk SQL - III

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

V dalších letech se pak začaly objevovat první normy pro jazyk C++ (ISO/IEC 14882:1998; ISO/IEC 9899:1999; ISO/IEC 14882:2003; ISO/IEC 14882:2011).

Úvod do programování v jazyce Java

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

PB161 Programování v jazyce C++ Přednáška 10

Úvod do programování - Java. Cvičení č.4

Mělká a hluboká kopie

Úvod do programovacích jazyků (Java)

IUJCE 07/08 Přednáška č. 4. v paměti neexistuje. v paměti existuje

Objektově orientované programování

Aplikace Embedded systémů v Mechatronice. Michal Bastl A2/713a

EVROPSKÝ SOCIÁLNÍ FOND. Úvod do PHP PRAHA & EU INVESTUJEME DO VAŠÍ BUDOUCNOSTI

Programovanie v jazyku C - struktury a polia

Práce s řetězci. IUJCE Přednáška č. 10. string.h. vrací: délku řetězce str (bez '\0')

IB111 Úvod do programování skrze Python Přednáška 7

Dynamika objektů. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze

Ukazatele, dynamická alokace

Konstruktory a destruktory

Programování v Javě I. Únor 2009

Programování 2 (NMIN102) Soubory. RNDr. Michal Žemlička, Ph.D.

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Práce s pamětí a předávání parametrů. Úvod do programování 1

Lineární spojový seznam (úvod do dynamických datových struktur)

Příkazy preprocesoru - Před překladem kódu překladačem mu předpřipraví kód preprocesor - Preprocesor vypouští nadbytečné (prázdné) mezery a řádky -

Programování v Javě I. Leden 2008

Metody připojování periferií

Skriptovací jazyky. Obsah

Základy programování (IZP)

PB přednáška (23. listopadu 2015)

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

PB161 Programování v jazyce C++ Přednáška 4

Programování v C++ První kroky

Programovací jazyk C(++) C++ area->vm_mm->locked_vm -= len >> PAGE_SHIFT;

Abstraktní třídy, polymorfní struktury

8 Třídy, objekty, metody, předávání argumentů metod

PB161 Základy OOP. Tomáš Brukner

Druhy souborů. textové. binární. nestrukturované txt strukturované - ini, xml, csv. veřejné bmp, jpg, wav proprietární docx, cdr, psd

5 Rekurze a zásobník. Rekurzivní volání metody

Výrazy, operace, příkazy

Více o konstruktorech a destruktorech

PB071 Programování v jazyce C

Tabulka fotbalové ligy

Základy programování 2 KMI/ZP2

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

Jazyk C++ I. Šablony 3

Databáze I. Přednáška 7

NPRG031 Programování II --- 2/2 Z, Zk

Data, výrazy, příkazy

Vláknové programování část V

SPJA, cvičení 1. ipython, python, skripty. základy syntaxe: základní datové typy, řetězce. podmínky: if-elif-else, vyhodnocení logických výrazů

PODOBÁ SE JAZYKU C S NĚKTERÝMI OMEZENÍMI GLOBÁLNÍ PROMĚNNÉ. NSWI162: Sémantika programů 2

<surface name="pozadi" file="obrazky/pozadi/pozadi.png"/> ****************************************************************************

Knihovna XmlLib TXV druhé vydání říjen 2012 změny vyhrazeny

Čipové karty Lekařská informatika

Prezentace a vysvětlení programového prostředí NXC

Lekce 19 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Transkript:

Účel modulů v jazyku C: Rozšiřování a upravování stávající funkcionality PLToolbox, Orafce Vlastní datové typy PostGIS Hstore Citext Zpřístupnění funkcionality z knihoven PL/R PL/Perl, PL/Python xml2 - (contrib)

Modul v C lze použít k obfuskaci kódu

BpChar ArrayType VarChar Numeric Datum znamená hodnotu Bytea Text Bool Int32 CString Pointer Datum znamená referenci varlena v1_len[4] v1_dat[1] Typedef Datum *unsigned int int

FunctionCallInfoData FunctionCallInfo bool short Datum bool isnull nargs arg[func_max_args] argnull[func_max_args] #define PG_FUNCTION_ARGS FunctionCallInfo fcinfo #define PG_NARGS() (fcinfo->nargs) #define PG_ARGISNULL(n) (fcinfo->argnull[n]) #define PG_GETARG_DATUM(n) (fcinfo->arg[n]) #define PG_GETARG_INT32(n) DatumGetInt32(PG_GETARG_DATUM(n)) #define PG_RETURN_INT32(x) return Int32GetDatum(x) #define PG_RETURN_NULL() \ do do fcinfo->isnull = true; return (Datum) 0; 0; } while(0)

Datum Int32_sum(PG_FUNCTION_ARGS) int a = PG_GETARG_INT32(0); int b = PG_GETARG_INT32(1); } PG_RETURN_INT32(a + b) FUNKCE MUSÍ BÝT OZNAČENA ATRIBUTEM STRICT

Datum Int32_sum(FunctionCallInfo fcinfo) int a = DatumGetInt32(fcinfo->arg[0]); int b = DatumGetInt32(fcinfo->arg[1]); } Return Int32GetDatum(a + b);

#define PointerGetDatum(X) ((Datum) X) #define DatumGetPointer(X) ((Pointer) X) #define Int32GetDatum(X) ((Datum) SET_4_BYTES(X)) #define DatumGetInt32(X) ((int32) GET_4_BYTES(X)) #define CStringGetDatum(X) (PointerGetDatum(X)) #define DatumGetCString(X) ((char *) DatumGetPointer(X)) #define PG_DETOAST_DATUM(X) \ pg_detoast_datum((struct varlena *) DatumGetPointer(X)) #define DatumGetTextP(X) ((text *) PG_DETOAST_DATUM(X)) #define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X)) #define PG_GETARG_TEXT_P(X) DatumGetTextP(PG_GETARG_DATUM(X)) #define PG_RETURN_TEXT_P(X) PG_RETURN_POINTER(X)

FUNKCE MUSÍ BÝT OZNAČENA ATRIBUTEM STRICT Datum concat(pg_function_args) text *a = PG_GETARG_TEXT_P(0); text *b = PG_GETARG_TEXT_P(1); text *result; int len1, len2, len; char *ptr; len1 = VARSIZE(a) VARHDRSZ; len2 = VARSIZE(b) VARHDRSZ; Len = len1 + len2 + VARHDRSZ; result = (text *) palloc(len); ptr = VARDATA(result); memcpy(ptr, VARDATA(a), len1); memcpy(ptr + len1, VARDATA(b), len2); SET_VARSIZE(result, len); } PG_RETURN_TEXT_P(result);

Text *a = PG_GETARG_TEXT_P(0); text *a = ((text *) pg_detoast_datum( (struct *varlena) DatumGetPointer((fcinfo->arg[0]))))

text * Datum 88 AA HH OO JJ < 2KB raw < 8KB compressed > 8KB toasted PG_DETOAST_DATUM (struct varlena *) *) varattrib_4b.va_4byte varattrib_4b.va_compressed varatt_external Data Page 88 AA HH OO JJ 88 ref Data Page XXX_toast 2KB blok bin dat 2KB blok bin dat

#include lib/stringinfo Datum HelloFunc(PG_FUNCTION_ARGS) StringInfoData ds; char *str; initstringinfo(&ds); str = text_to_cstring(pg_getarg_text_p(0)); appendstringinfo(&ds, Hello %s, str); } PG_RETURN_TEXT_P(cstring_to_text_with_len(ds.data, ds.len)); StringInfoData char Int Int Int Int Int Int *data; len; maxlen; cursor;

CREATE OR REPLACE FUNCTION hello_func(text) RETURNS text AS '$libdir/hello', 'pst_hello_func' LANGUAGE C IMMUTABLE STRICT;

... appendstringinfo(&ds, Hello %s, str); result = cstring_to_text_with_len(ds.data, ds.len); result = DatumGetTextP( DirectFunctionCall1(upper, TextPGetDatum(result))); } PG_RETURN_TEXT_P(result);

#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs,..) \ do do \ (Fcinfo).isnull = false; \ (Fcinfo).nargs = Nargs; \ } while (0) Datum DirectFunctionCall1(PGFunction func, Datum arg1) FunctionCallInfoData fcinfo; Datum result; InitFunctionCallInfoData(&fcinfo, NULL, 1, 1,..); fcinfo.arg[0] = arg1; fcinfo.argisnull[0] = false; } result = (*func) (fcinfo) if if (fcinfo.isnull) elog(error, function %p %p returns NULL, func); return result;

POZOR funkce musí být STRICT Datum pst_left(pg_function_args) text *txt = PG_GETARG_TEXT_P(0); text *result; char *str = VARDATA(txt); int len = VARSIZE(txt) VARHDRSZ; char *ptr = *str; int int processed = 0; 0; int n = PG_GETARG_INT32(1); int mblen; POZOR používá se UTF8 while (processed < len) If If (n-- == == 0) 0) break; mblen = pg_mblen(ptr); ptr += += mblen; processed += += mblen; } } result = cstring_to_text_with_len(str, processed); PG_RETURN_TEXT_P(result);

/* * Bez signatury je funkce volána * s klasickou C (0) konvencí předávání * parametrů! Tudíž pokud dojde k odkazu * na fcinfo, dojde k pádu aplikace. */ PG_FUNCTION_INFO_V1(pst_left); Datum pst_left(pg_function_args)... PG_RETURN_TEXT_P(result); }

const Pg_finfo_record * pg_finfo_pst_left (void) static const pg_finfo_record myfinfo = 1}; return &myfinfo; } const Pg_finfo_record * fetch_finfo_record(void *filehandle, char *funcname) infofuncname = (char *) *) palloc(strlen(funcname) + 10); strcpy(infofuncname, pg_finfo_ ); strcat(infofuncname, funcname); infofunc = lookup_external_function(filehandle, Infofuncname); if if (infofunc == == 0) 0) /* /* version 0; 0; */ */ } inforec = (*infofunc)(); } switch (inforec->api_version)...

PG_FUNCTION_INFO_V1(pst_left); Datum pst_left(pg_function_args) text *txt = PG_GETARG_TEXT_P(0); int n = PG_GETARG_INT32(1);... } PG_RETURN_TEXT_P(result);

CREATE OR REPLACE FUNCTION left(text, int) RETURNS text AS '$libdir/hello', 'pst_left' LANGUAGE C IMMUTABLE STRICT;

Nepodceňovat varování překladače Nezapomínat na signaturu V1 volající konvence Překlad PostgreSQL s parametrem enable-cassert Echo elog(notice,... ) Je třeba zvládnout základy gdb bt backtrace z core dumpu

TopMemoryContext TopTransactionContext CurTransactionContext temp context MemoryContextAlloc(context, size) Alokovaná paměť palloc(size) pfree(ptr) Alokovaná paměť

MemoryContext oldctx; MemoryContext tmpctx; tmpctx = AllocSetContextCreate(CurrentMemoryContext, "plpsm execution context", 0, 8 * 1024, 8 * 1024 * 1024); oldctx = MemoryContextSwitchTo(tmpctx);... ptr = palloc(sizeof(..));... MemoryContextReset(tmpctx); MemoryContextSwitchTo(oldctxt);

/* /* * Pokud pracujeme s rozumě dlouhými řetězci mimo cyklu nemusíme explicitně * uvolňovat alokovanou paměť. Po Po vykonání funkce executor provede reset * aktuálního paměťového kontextu. Pozor k tomu nedochází při přímém volání * funkce skrze DirectFunctionCall. */ */ #include lib/stringinfo Datum HelloFunc(PG_FUNCTION_ARGS) StringInfoData ds; char *str; /* /* paměť je je alokována string builderem */ */ initstringinfo(&ds); /* /* * text_to_cstring alokuje paměť, případně * DETOAST alokuje další paměť a pracujeme * s kopií dat. */ */ str = text_to_cstring(pg_getarg_text_p(0)); appendstringinfo(&ds, Hello %s, str); } /* /* cstring_to_text_with_len alokuje paměť */ */ PG_RETURN_TEXT_P(cstring_to_text_with_len(ds.data, ds.len));

#ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif #define PG_MODULE_MAGIC \ const Pg_magic_struct * \ Pg_magic_func(void) \ \ static const Pg_magic_struct Pg_magic_data = \ sizeof(pg_magic_struct), \ PG_VERSION_NUM / 100, \ FUNC_MAX_ARGS, \ INDEX_MAX_KEYS, \ NAMEDATALEN, \ FLOAT4PASSBYVAL, \ FLOAT8PASSBYVAL \ }; \ return &Pg_magic_data; \ } \

/* Check the magic function to determine compatibility */ magic_func = (PGModuleMagicFunction) pg_dlsym(file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING); if (magic_func) const Pg_magic_struct *magic_data_ptr = (*magic_func) (); if (magic_data_ptr->len!= magic_data.len memcmp(magic_data_ptr, &magic_data, magic_data.len)!= 0) /* copy data block before unlinking library */ Pg_magic_struct module_magic_data = *magic_data_ptr;

Nepodceňovat varování překladače Nezapomínat na signaturu modulu Nezapomínat na signaturu V1 volající konvence Překlad PostgreSQL s parametrem enable-cassert Echo elog(notice,... ) Je třeba zvládnout základy gdb bt backtrace z core dumpu

char *result = NULL; char *query = text_to_cstring(pg_getarg_text_p(0)); SPI_connect(); ret = SPI_exec(query, 0); if (ret > 0 && SPI_tuptable!= NULL) TupleDesc tupdesc = SPI_tuptable->tupdesc; SPITupleTable *tuptable = SPI_tuptable; HeapTuple tuple = tuptable->vals[0]; Pozor nefunguje! if (tupdesc->natts > 1) elog(error, Query returned more columns ); if (SPI_processed > 1) elog(error, Query returned more rows ); else if (SPI_processed == 1) result = SPI_getvalue(tuple, tupdesc, 1); } SPI_finish(); if (result!= NULL) PG_RETURN_TEXT_P(cstring_to_text(result)) else PG_RETURN_NULL();

/* nefunkční */ SPI_finish(); if (result!= NULL) /* je zkopírován neplatný blok paměti */ PG_RETURN_TEXT_P(cstring_to_text(result)) else PG_RETURN_NULL(); špatně if (result!= NULL) spictx = MemoryContextSwitchTo(callCtx); result = cstring_to_text(result); MemoryContextSwitchTo(spiCtx); } SPI_finish(); if (result) PG_RETURN_TEXT_P(result); else PG_RETURN_NULL(); OK

callctx SPI procctx execctx result ahoj

callctx Po SPI_finish SPI procctx execctx result ahoj

postgres=# select eval('select $1 $1 + $2', 10, 3.14); eval ------- 13.14 (1 (1 row) postgres=# select eval('select $1 $1 '' '' '' '' $2', 'Hello', 'World'); eval ------------- Hello World (1 (1 row) postgres=# select eval('select upper($1 '' '' '' '' $2)', 'Hello', 'World'); eval ------------- HELLO WORLD (1 (1 row)

Nepodceňovat varování překladače Nezapomínat na signaturu modulu Nezapomínat na signaturu V1 volající konvence Překlad PostgreSQL s parametrem enable-cassert Echo elog(notice,... ) Je třeba zvládnout základy gdb bt backtrace z core dumpu Když něco nefunguje, zamyslet se nad správou paměti