1
1
/*-------------------------------------------------------------------------
2
2
*
3
3
* dummy_toaster.c
4
- * Dummy toaster for Toaster API.
4
+ * Dummy toaster - sample toaster for Toaster API.
5
5
*
6
6
* Portions Copyright (c) 2016-2021, PostgreSQL Global Development Group
7
7
* Portions Copyright (c) 1990-1993, Regents of the University of California
14
14
#include "postgres.h"
15
15
#include "fmgr.h"
16
16
#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"
17
37
#include "nodes/makefuncs.h"
18
38
19
39
PG_MODULE_MAGIC ;
@@ -22,68 +42,106 @@ PG_FUNCTION_INFO_V1(dummy_toaster_handler);
22
42
#define MAX_DUMMY_CHUNK_SIZE 1024
23
43
24
44
/*
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
+ *
32
48
*/
33
49
static Datum
34
- dummy_detoast (Relation toast_rel , Datum toast_ptr ,
50
+ dummy_detoast (Datum toast_ptr ,
35
51
int offset , int length )
36
52
{
53
+ struct varlena * attr = (struct varlena * ) DatumGetPointer (toast_ptr );
37
54
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
+
39
64
return PointerGetDatum (result );
40
65
}
41
66
42
67
/*
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
44
70
*/
45
71
static Datum
46
72
dummy_toast (Relation toast_rel , Oid toasterid ,
47
73
Datum value , Datum oldvalue ,
48
74
int max_inline_size , int options )
49
75
{
76
+ struct varlena * attr ;
50
77
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
+
52
113
return PointerGetDatum (result );
53
114
}
54
115
55
116
/*
56
- * Dummy deltoast function, does nothing
117
+ * Dummy delete function
57
118
*/
58
119
static void
59
120
dummy_delete (Datum value , bool is_speculative )
60
121
{
61
122
}
62
123
63
124
/*
64
- * Dummy init function, does nothing
125
+ * Dummy Validate, always returns True
126
+ *
65
127
*/
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 )
69
131
{
132
+ bool result = true;
133
+ return result ;
70
134
}
71
135
72
136
/*
73
137
* Dummy validation function, always returns TRUE
74
138
*/
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 )
78
142
{
79
- return true;
80
143
}
81
144
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
- */
87
145
Datum
88
146
dummy_toaster_handler (PG_FUNCTION_ARGS )
89
147
{
@@ -95,7 +153,7 @@ dummy_toaster_handler(PG_FUNCTION_ARGS)
95
153
tsr -> detoast = dummy_detoast ;
96
154
tsr -> deltoast = dummy_delete ;
97
155
tsr -> get_vtable = NULL ;
98
- tsr -> toastervalidate = NULL ;
156
+ tsr -> toastervalidate = dummy_toaster_validate ;
99
157
100
158
PG_RETURN_POINTER (tsr );
101
159
}
0 commit comments