11/*-------------------------------------------------------------------------
22 *
33 * dummy_toaster.c
4- * Dummy toaster for Toaster API.
4+ * Dummy toaster - sample toaster for Toaster API.
55 *
66 * Portions Copyright (c) 2016-2021, PostgreSQL Global Development Group
77 * Portions Copyright (c) 1990-1993, Regents of the University of California
1414#include "postgres.h"
1515#include "fmgr.h"
1616#include "access/toasterapi.h"
17+ #include "access/heaptoast.h"
18+ #include "access/htup_details.h"
19+ #include "catalog/pg_toaster.h"
20+ #include "commands/defrem.h"
21+ #include "utils/builtins.h"
22+ #include "utils/syscache.h"
23+ #include "access/toast_compression.h"
24+ #include "access/xact.h"
25+ #include "catalog/binary_upgrade.h"
26+ #include "catalog/catalog.h"
27+ #include "catalog/dependency.h"
28+ #include "catalog/heap.h"
29+ #include "catalog/index.h"
30+ #include "catalog/namespace.h"
31+ #include "catalog/pg_am.h"
32+ #include "catalog/pg_namespace.h"
33+ #include "catalog/pg_opclass.h"
34+ #include "catalog/pg_type.h"
35+ #include "catalog/toasting.h"
36+ #include "miscadmin.h"
1737#include "nodes/makefuncs.h"
1838
1939PG_MODULE_MAGIC ;
@@ -22,68 +42,106 @@ PG_FUNCTION_INFO_V1(dummy_toaster_handler);
2242#define MAX_DUMMY_CHUNK_SIZE 1024
2343
2444/*
25- * Dummy Toaster is a sample custom toaster for developers to show Toaster API
26- * functionality and correct way to add new Toasters to PgSQL.
27- */
28-
29-
30- /*
31- * Dummy detoast function, does nothing
45+ * Dummy Detoast function, receives single varatt_custom pointer,
46+ * detoasts it to varlena.
47+ *
3248 */
3349static Datum
34- dummy_detoast (Relation toast_rel , Datum toast_ptr ,
50+ dummy_detoast (Datum toast_ptr ,
3551 int offset , int length )
3652{
53+ struct varlena * attr = (struct varlena * ) DatumGetPointer (toast_ptr );
3754 struct varlena * result ;
38- result = palloc (0 );
55+
56+ Assert (VARATT_IS_EXTERNAL (attr ));
57+ Assert (VARATT_IS_CUSTOM (attr ));
58+
59+ result = palloc (VARATT_CUSTOM_GET_DATA_RAW_SIZE (attr ));
60+ SET_VARSIZE (result , VARATT_CUSTOM_GET_DATA_RAW_SIZE (attr ));
61+ memcpy (VARDATA (result ), VARATT_CUSTOM_GET_DATA (attr ),
62+ VARATT_CUSTOM_GET_DATA_RAW_SIZE (attr ) - VARHDRSZ );
63+
3964 return PointerGetDatum (result );
4065}
4166
4267/*
43- * Dummy Toast function, does nothing
68+ * Dummy Toast function, receives varlena pointer, creates single varatt_custom
69+ * varlena size is limited to 1024 bytes
4470 */
4571static Datum
4672dummy_toast (Relation toast_rel , Oid toasterid ,
4773 Datum value , Datum oldvalue ,
4874 int max_inline_size , int options )
4975{
76+ struct varlena * attr ;
5077 struct varlena * result ;
51- result = palloc (0 );
78+ int len ;
79+ attr = pg_detoast_datum ((struct varlena * )DatumGetPointer (value ));
80+
81+ if (VARSIZE_ANY_EXHDR (attr ) > MAX_DUMMY_CHUNK_SIZE )
82+ {
83+ ereport (ERROR ,
84+ (errcode (ERRCODE_DATA_CORRUPTED ),
85+ errmsg_internal ("Data <%d> size exceeds MAX_DUMMY_CHUNK_SIZE <%d>" ,
86+ (int )VARSIZE_ANY_EXHDR (attr ), MAX_DUMMY_CHUNK_SIZE )));
87+
88+ }
89+
90+ len = VARATT_CUSTOM_SIZE (VARSIZE_ANY_EXHDR (attr ));
91+
92+ if (max_inline_size > 0 && len > max_inline_size )
93+ {
94+ ereport (ERROR ,
95+ (errcode (ERRCODE_DATA_CORRUPTED ),
96+ errmsg_internal ("Data <%d> size exceeds max inline size <%d>" ,
97+ len , max_inline_size )));
98+ }
99+
100+ result = palloc (len );
101+
102+ SET_VARTAG_EXTERNAL (result , VARTAG_CUSTOM );
103+ VARATT_CUSTOM_SET_DATA_RAW_SIZE (result , VARSIZE_ANY_EXHDR (attr ) + VARHDRSZ );
104+ VARATT_CUSTOM_SET_DATA_SIZE (result , len );
105+ VARATT_CUSTOM_SET_TOASTERID (result , toasterid );
106+
107+ memcpy (VARATT_CUSTOM_GET_DATA (result ), VARDATA_ANY (attr ),
108+ VARSIZE_ANY_EXHDR (attr ));
109+
110+ if ((char * )attr != DatumGetPointer (value ))
111+ pfree (attr );
112+
52113 return PointerGetDatum (result );
53114}
54115
55116/*
56- * Dummy deltoast function, does nothing
117+ * Dummy delete function
57118 */
58119static void
59120dummy_delete (Datum value , bool is_speculative )
60121{
61122}
62123
63124/*
64- * Dummy init function, does nothing
125+ * Dummy Validate, always returns True
126+ *
65127 */
66- static void
67- dummy_toast_init ( Relation rel , Datum reloptions , LOCKMODE lockmode ,
68- bool check , Oid OIDOldToast )
128+ static bool
129+ dummy_toaster_validate ( Oid typeoid , char storage , char compression ,
130+ Oid amoid , bool false_ok )
69131{
132+ bool result = true;
133+ return result ;
70134}
71135
72136/*
73137 * Dummy validation function, always returns TRUE
74138 */
75- static bool
76- dummy_toaster_validate ( Oid typeoid , char storage , char compression ,
77- Oid amoid , bool false_ok )
139+ static void
140+ dummy_toast_init ( Relation rel , Oid toastoid , Oid toastindexoid , Datum reloptions , LOCKMODE lockmode ,
141+ bool check , Oid OIDOldToast )
78142{
79- return true;
80143}
81144
82- /*
83- * Dummy toaster handler.
84- * All Toaster functions declared in toasterapi.h and implemented in Custom
85- * Toasters must be assigned to TsrRoutine structure
86- */
87145Datum
88146dummy_toaster_handler (PG_FUNCTION_ARGS )
89147{
@@ -95,7 +153,7 @@ dummy_toaster_handler(PG_FUNCTION_ARGS)
95153 tsr -> detoast = dummy_detoast ;
96154 tsr -> deltoast = dummy_delete ;
97155 tsr -> get_vtable = NULL ;
98- tsr -> toastervalidate = NULL ;
156+ tsr -> toastervalidate = dummy_toaster_validate ;
99157
100158 PG_RETURN_POINTER (tsr );
101159}
0 commit comments