1 /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
2 
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License, version 2.0,
5   as published by the Free Software Foundation.
6 
7   This program is also distributed with certain software (including
8   but not limited to OpenSSL) that is licensed under separate terms,
9   as designated in a particular file or component or in included license
10   documentation.  The authors of MySQL hereby grant you an additional
11   permission to link the program and your derivative works with the
12   separately licensed software that they have included with MySQL.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License, version 2.0, for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
22 
23 #ifndef PFS_TABLE_HELPER_H
24 #define PFS_TABLE_HELPER_H
25 
26 #include "pfs_column_types.h"
27 #include "pfs_stat.h"
28 #include "pfs_timer.h"
29 #include "pfs_engine_table.h"
30 #include "pfs_instr_class.h"
31 #include "pfs_digest.h"
32 
33 /*
34   Write MD5 hash value in a string to be used
35   as DIGEST for the statement.
36 */
37 #define MD5_HASH_TO_STRING(_hash, _str)                    \
38   sprintf(_str, "%02x%02x%02x%02x%02x%02x%02x%02x"         \
39                 "%02x%02x%02x%02x%02x%02x%02x%02x",        \
40           _hash[0], _hash[1], _hash[2], _hash[3],          \
41           _hash[4], _hash[5], _hash[6], _hash[7],          \
42           _hash[8], _hash[9], _hash[10], _hash[11],        \
43           _hash[12], _hash[13], _hash[14], _hash[15])
44 
45 #define MD5_HASH_TO_STRING_LENGTH 32
46 
47 struct PFS_host;
48 struct PFS_user;
49 struct PFS_account;
50 struct PFS_object_name;
51 struct PFS_program;
52 class System_variable;
53 class Status_variable;
54 
55 /**
56   @file storage/perfschema/table_helper.h
57   Performance schema table helpers (declarations).
58 */
59 
60 /**
61   @addtogroup Performance_schema_tables
62   @{
63 */
64 
65 /** Namespace, internal views used within table setup_instruments. */
66 struct PFS_instrument_view_constants
67 {
68   static const uint FIRST_VIEW= 1;
69   static const uint VIEW_MUTEX= 1;
70   static const uint VIEW_RWLOCK= 2;
71   static const uint VIEW_COND= 3;
72   static const uint VIEW_FILE= 4;
73   static const uint VIEW_TABLE= 5;
74   static const uint VIEW_SOCKET= 6;
75   static const uint VIEW_IDLE= 7;
76   static const uint VIEW_METADATA= 8;
77   static const uint LAST_VIEW= 8;
78 };
79 
80 /** Namespace, internal views used within object summaries. */
81 struct PFS_object_view_constants
82 {
83   static const uint FIRST_VIEW= 1;
84   static const uint VIEW_TABLE= 1;
85   static const uint VIEW_PROGRAM= 2;
86   static const uint LAST_VIEW= 2;
87 };
88 
89 /** Row fragment for column HOST. */
90 struct PFS_host_row
91 {
92   /** Column HOST. */
93   char m_hostname[HOSTNAME_LENGTH];
94   /** Length in bytes of @c m_hostname. */
95   uint m_hostname_length;
96 
97   /** Build a row from a memory buffer. */
98   int make_row(PFS_host *pfs);
99   /** Set a table field from the row. */
100   void set_field(Field *f);
101 };
102 
103 /** Row fragment for column USER. */
104 struct PFS_user_row
105 {
106   /** Column USER. */
107   char m_username[USERNAME_LENGTH];
108   /** Length in bytes of @c m_username. */
109   uint m_username_length;
110 
111   /** Build a row from a memory buffer. */
112   int make_row(PFS_user *pfs);
113   /** Set a table field from the row. */
114   void set_field(Field *f);
115 };
116 
117 /** Row fragment for columns USER, HOST. */
118 struct PFS_account_row
119 {
120   /** Column USER. */
121   char m_username[USERNAME_LENGTH];
122   /** Length in bytes of @c m_username. */
123   uint m_username_length;
124   /** Column HOST. */
125   char m_hostname[HOSTNAME_LENGTH];
126   /** Length in bytes of @c m_hostname. */
127   uint m_hostname_length;
128 
129   /** Build a row from a memory buffer. */
130   int make_row(PFS_account *pfs);
131   /** Set a table field from the row. */
132   void set_field(uint index, Field *f);
133 };
134 
135 /** Row fragment for columns DIGEST, DIGEST_TEXT. */
136 struct PFS_digest_row
137 {
138   /** Column SCHEMA_NAME. */
139   char m_schema_name[NAME_LEN];
140   /** Length in bytes of @c m_schema_name. */
141   uint m_schema_name_length;
142   /** Column DIGEST. */
143   char m_digest[COL_DIGEST_SIZE];
144   /** Length in bytes of @c m_digest. */
145   uint m_digest_length;
146   /** Column DIGEST_TEXT. */
147   String m_digest_text;
148 
149   /** Build a row from a memory buffer. */
150   int make_row(PFS_statements_digest_stat*);
151   /** Set a table field from the row. */
152   void set_field(uint index, Field *f);
153 };
154 
155 /** Row fragment for column EVENT_NAME. */
156 struct PFS_event_name_row
157 {
158   /** Column EVENT_NAME. */
159   const char *m_name;
160   /** Length in bytes of @c m_name. */
161   uint m_name_length;
162 
163   /** Build a row from a memory buffer. */
make_rowPFS_event_name_row164   inline void make_row(PFS_instr_class *pfs)
165   {
166     m_name= pfs->m_name;
167     m_name_length= pfs->m_name_length;
168   }
169 
170   /** Set a table field from the row. */
set_fieldPFS_event_name_row171   inline void set_field(Field *f)
172   {
173     PFS_engine_table::set_field_varchar_utf8(f, m_name, m_name_length);
174   }
175 };
176 
177 /** Row fragment for columns OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME. */
178 struct PFS_object_row
179 {
180   /** Column OBJECT_TYPE. */
181   enum_object_type m_object_type;
182   /** Column SCHEMA_NAME. */
183   char m_schema_name[NAME_LEN];
184   /** Length in bytes of @c m_schema_name. */
185   uint m_schema_name_length;
186   /** Column OBJECT_NAME. */
187   char m_object_name[NAME_LEN];
188   /** Length in bytes of @c m_object_name. */
189   uint m_object_name_length;
190 
191   /** Build a row from a memory buffer. */
192   int make_row(PFS_table_share *pfs);
193   int make_row(PFS_program *pfs);
194   int make_row(const MDL_key *pfs);
195   /** Set a table field from the row. */
196   void set_field(uint index, Field *f);
197   void set_nullable_field(uint index, Field *f);
198 };
199 
200 /** Row fragment for columns OBJECT_TYPE, SCHEMA_NAME, OBJECT_NAME, INDEX_NAME. */
201 struct PFS_index_row
202 {
203   PFS_object_row m_object_row;
204   /** Column INDEX_NAME. */
205   char m_index_name[NAME_LEN];
206   /** Length in bytes of @c m_index_name. */
207   uint m_index_name_length;
208 
209   /** Build a row from a memory buffer. */
210   int make_row(PFS_table_share *pfs, PFS_table_share_index *pfs_index,
211                uint table_index);
212   /** Set a table field from the row. */
213   void set_field(uint index, Field *f);
214 };
215 
216 /** Row fragment for single statistics columns (COUNT, SUM, MIN, AVG, MAX) */
217 struct PFS_stat_row
218 {
219   /** Column COUNT_STAR. */
220   ulonglong m_count;
221   /** Column SUM_TIMER_WAIT. */
222   ulonglong m_sum;
223   /** Column MIN_TIMER_WAIT. */
224   ulonglong m_min;
225   /** Column AVG_TIMER_WAIT. */
226   ulonglong m_avg;
227   /** Column MAX_TIMER_WAIT. */
228   ulonglong m_max;
229 
resetPFS_stat_row230   inline void reset()
231   {
232     m_count= 0;
233     m_sum= 0;
234     m_min= 0;
235     m_avg= 0;
236     m_max= 0;
237   }
238 
239   /** Build a row with timer fields from a memory buffer. */
setPFS_stat_row240   inline void set(time_normalizer *normalizer, const PFS_single_stat *stat)
241   {
242     m_count= stat->m_count;
243 
244     if ((m_count != 0) && stat->has_timed_stats())
245     {
246       m_sum= normalizer->wait_to_pico(stat->m_sum);
247       m_min= normalizer->wait_to_pico(stat->m_min);
248       m_max= normalizer->wait_to_pico(stat->m_max);
249       m_avg= normalizer->wait_to_pico(stat->m_sum / m_count);
250     }
251     else
252     {
253       m_sum= 0;
254       m_min= 0;
255       m_avg= 0;
256       m_max= 0;
257     }
258   }
259 
260   /** Set a table field from the row. */
set_fieldPFS_stat_row261   void set_field(uint index, Field *f)
262   {
263     switch (index)
264     {
265       case 0: /* COUNT */
266         PFS_engine_table::set_field_ulonglong(f, m_count);
267         break;
268       case 1: /* SUM */
269         PFS_engine_table::set_field_ulonglong(f, m_sum);
270         break;
271       case 2: /* MIN */
272         PFS_engine_table::set_field_ulonglong(f, m_min);
273         break;
274       case 3: /* AVG */
275         PFS_engine_table::set_field_ulonglong(f, m_avg);
276         break;
277       case 4: /* MAX */
278         PFS_engine_table::set_field_ulonglong(f, m_max);
279         break;
280       default:
281         assert(false);
282     }
283   }
284 };
285 
286 /** Row fragment for timer and byte count stats. Corresponds to PFS_byte_stat */
287 struct PFS_byte_stat_row
288 {
289   PFS_stat_row m_waits;
290   ulonglong    m_bytes;
291 
292   /** Build a row with timer and byte count fields from a memory buffer. */
setPFS_byte_stat_row293   inline void set(time_normalizer *normalizer, const PFS_byte_stat *stat)
294   {
295     m_waits.set(normalizer, stat);
296     m_bytes= stat->m_bytes;
297   }
298 };
299 
300 /** Row fragment for table io statistics columns. */
301 struct PFS_table_io_stat_row
302 {
303   PFS_stat_row m_all;
304   PFS_stat_row m_all_read;
305   PFS_stat_row m_all_write;
306   PFS_stat_row m_fetch;
307   PFS_stat_row m_insert;
308   PFS_stat_row m_update;
309   PFS_stat_row m_delete;
310 
311   /** Build a row from a memory buffer. */
setPFS_table_io_stat_row312   inline void set(time_normalizer *normalizer, const PFS_table_io_stat *stat)
313   {
314     PFS_single_stat all_read;
315     PFS_single_stat all_write;
316     PFS_single_stat all;
317 
318     m_fetch.set(normalizer, & stat->m_fetch);
319 
320     all_read.aggregate(& stat->m_fetch);
321 
322     m_insert.set(normalizer, & stat->m_insert);
323     m_update.set(normalizer, & stat->m_update);
324     m_delete.set(normalizer, & stat->m_delete);
325 
326     all_write.aggregate(& stat->m_insert);
327     all_write.aggregate(& stat->m_update);
328     all_write.aggregate(& stat->m_delete);
329 
330     all.aggregate(& all_read);
331     all.aggregate(& all_write);
332 
333     m_all_read.set(normalizer, & all_read);
334     m_all_write.set(normalizer, & all_write);
335     m_all.set(normalizer, & all);
336   }
337 };
338 
339 /** Row fragment for table lock statistics columns. */
340 struct PFS_table_lock_stat_row
341 {
342   PFS_stat_row m_all;
343   PFS_stat_row m_all_read;
344   PFS_stat_row m_all_write;
345   PFS_stat_row m_read_normal;
346   PFS_stat_row m_read_with_shared_locks;
347   PFS_stat_row m_read_high_priority;
348   PFS_stat_row m_read_no_insert;
349   PFS_stat_row m_read_external;
350   PFS_stat_row m_write_allow_write;
351   PFS_stat_row m_write_concurrent_insert;
352   PFS_stat_row m_write_low_priority;
353   PFS_stat_row m_write_normal;
354   PFS_stat_row m_write_external;
355 
356   /** Build a row from a memory buffer. */
setPFS_table_lock_stat_row357   inline void set(time_normalizer *normalizer, const PFS_table_lock_stat *stat)
358   {
359     PFS_single_stat all_read;
360     PFS_single_stat all_write;
361     PFS_single_stat all;
362 
363     m_read_normal.set(normalizer, & stat->m_stat[PFS_TL_READ]);
364     m_read_with_shared_locks.set(normalizer, & stat->m_stat[PFS_TL_READ_WITH_SHARED_LOCKS]);
365     m_read_high_priority.set(normalizer, & stat->m_stat[PFS_TL_READ_HIGH_PRIORITY]);
366     m_read_no_insert.set(normalizer, & stat->m_stat[PFS_TL_READ_NO_INSERT]);
367     m_read_external.set(normalizer, & stat->m_stat[PFS_TL_READ_EXTERNAL]);
368 
369     all_read.aggregate(& stat->m_stat[PFS_TL_READ]);
370     all_read.aggregate(& stat->m_stat[PFS_TL_READ_WITH_SHARED_LOCKS]);
371     all_read.aggregate(& stat->m_stat[PFS_TL_READ_HIGH_PRIORITY]);
372     all_read.aggregate(& stat->m_stat[PFS_TL_READ_NO_INSERT]);
373     all_read.aggregate(& stat->m_stat[PFS_TL_READ_EXTERNAL]);
374 
375     m_write_allow_write.set(normalizer, & stat->m_stat[PFS_TL_WRITE_ALLOW_WRITE]);
376     m_write_concurrent_insert.set(normalizer, & stat->m_stat[PFS_TL_WRITE_CONCURRENT_INSERT]);
377     m_write_low_priority.set(normalizer, & stat->m_stat[PFS_TL_WRITE_LOW_PRIORITY]);
378     m_write_normal.set(normalizer, & stat->m_stat[PFS_TL_WRITE]);
379     m_write_external.set(normalizer, & stat->m_stat[PFS_TL_WRITE_EXTERNAL]);
380 
381     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_ALLOW_WRITE]);
382     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_CONCURRENT_INSERT]);
383     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_LOW_PRIORITY]);
384     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE]);
385     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_EXTERNAL]);
386 
387     all.aggregate(& all_read);
388     all.aggregate(& all_write);
389 
390     m_all_read.set(normalizer, & all_read);
391     m_all_write.set(normalizer, & all_write);
392     m_all.set(normalizer, & all);
393   }
394 };
395 
396 /** Row fragment for stage statistics columns. */
397 struct PFS_stage_stat_row
398 {
399   PFS_stat_row m_timer1_row;
400 
401   /** Build a row from a memory buffer. */
setPFS_stage_stat_row402   inline void set(time_normalizer *normalizer, const PFS_stage_stat *stat)
403   {
404     m_timer1_row.set(normalizer, & stat->m_timer1_stat);
405   }
406 
407   /** Set a table field from the row. */
set_fieldPFS_stage_stat_row408   void set_field(uint index, Field *f)
409   {
410      m_timer1_row.set_field(index, f);
411   }
412 };
413 
414 /** Row fragment for statement statistics columns. */
415 struct PFS_statement_stat_row
416 {
417   PFS_stat_row m_timer1_row;
418   ulonglong m_error_count;
419   ulonglong m_warning_count;
420   ulonglong m_rows_affected;
421   ulonglong m_lock_time;
422   ulonglong m_rows_sent;
423   ulonglong m_rows_examined;
424   ulonglong m_created_tmp_disk_tables;
425   ulonglong m_created_tmp_tables;
426   ulonglong m_select_full_join;
427   ulonglong m_select_full_range_join;
428   ulonglong m_select_range;
429   ulonglong m_select_range_check;
430   ulonglong m_select_scan;
431   ulonglong m_sort_merge_passes;
432   ulonglong m_sort_range;
433   ulonglong m_sort_rows;
434   ulonglong m_sort_scan;
435   ulonglong m_no_index_used;
436   ulonglong m_no_good_index_used;
437 
438   /** Build a row from a memory buffer. */
setPFS_statement_stat_row439   inline void set(time_normalizer *normalizer, const PFS_statement_stat *stat)
440   {
441     if (stat->m_timer1_stat.m_count != 0)
442     {
443       m_timer1_row.set(normalizer, & stat->m_timer1_stat);
444 
445       m_error_count= stat->m_error_count;
446       m_warning_count= stat->m_warning_count;
447       m_lock_time= stat->m_lock_time * MICROSEC_TO_PICOSEC;
448       m_rows_affected= stat->m_rows_affected;
449       m_rows_sent= stat->m_rows_sent;
450       m_rows_examined= stat->m_rows_examined;
451       m_created_tmp_disk_tables= stat->m_created_tmp_disk_tables;
452       m_created_tmp_tables= stat->m_created_tmp_tables;
453       m_select_full_join= stat->m_select_full_join;
454       m_select_full_range_join= stat->m_select_full_range_join;
455       m_select_range= stat->m_select_range;
456       m_select_range_check= stat->m_select_range_check;
457       m_select_scan= stat->m_select_scan;
458       m_sort_merge_passes= stat->m_sort_merge_passes;
459       m_sort_range= stat->m_sort_range;
460       m_sort_rows= stat->m_sort_rows;
461       m_sort_scan= stat->m_sort_scan;
462       m_no_index_used= stat->m_no_index_used;
463       m_no_good_index_used= stat->m_no_good_index_used;
464     }
465     else
466     {
467       m_timer1_row.reset();
468 
469       m_error_count= 0;
470       m_warning_count= 0;
471       m_lock_time= 0;
472       m_rows_affected= 0;
473       m_rows_sent= 0;
474       m_rows_examined= 0;
475       m_created_tmp_disk_tables= 0;
476       m_created_tmp_tables= 0;
477       m_select_full_join= 0;
478       m_select_full_range_join= 0;
479       m_select_range= 0;
480       m_select_range_check= 0;
481       m_select_scan= 0;
482       m_sort_merge_passes= 0;
483       m_sort_range= 0;
484       m_sort_rows= 0;
485       m_sort_scan= 0;
486       m_no_index_used= 0;
487       m_no_good_index_used= 0;
488     }
489   }
490 
491   /** Set a table field from the row. */
492   void set_field(uint index, Field *f);
493 };
494 
495 /** Row fragment for stored program statistics. */
496 struct PFS_sp_stat_row
497 {
498   PFS_stat_row m_timer1_row;
499 
500   /** Build a row from a memory buffer. */
setPFS_sp_stat_row501   inline void set(time_normalizer *normalizer, const PFS_sp_stat *stat)
502   {
503     m_timer1_row.set(normalizer, & stat->m_timer1_stat);
504   }
505 
506   /** Set a table field from the row. */
set_fieldPFS_sp_stat_row507   inline void set_field(uint index, Field *f)
508   {
509     m_timer1_row.set_field(index, f);
510   }
511 };
512 
513 /** Row fragment for transaction statistics columns. */
514 struct PFS_transaction_stat_row
515 {
516   PFS_stat_row m_timer1_row;
517   PFS_stat_row m_read_write_row;
518   PFS_stat_row m_read_only_row;
519   ulonglong m_savepoint_count;
520   ulonglong m_rollback_to_savepoint_count;
521   ulonglong m_release_savepoint_count;
522 
523   /** Build a row from a memory buffer. */
setPFS_transaction_stat_row524   inline void set(time_normalizer *normalizer, const PFS_transaction_stat *stat)
525   {
526     /* Combine read write/read only stats */
527     PFS_single_stat all;
528     all.aggregate(&stat->m_read_only_stat);
529     all.aggregate(&stat->m_read_write_stat);
530 
531     m_timer1_row.set(normalizer, &all);
532     m_read_write_row.set(normalizer, &stat->m_read_write_stat);
533     m_read_only_row.set(normalizer, &stat->m_read_only_stat);
534   }
535 
536   /** Set a table field from the row. */
537   void set_field(uint index, Field *f);
538 };
539 
540 /** Row fragment for connection statistics. */
541 struct PFS_connection_stat_row
542 {
543   ulonglong m_current_connections;
544   ulonglong m_total_connections;
545 
setPFS_connection_stat_row546   inline void set(const PFS_connection_stat *stat)
547   {
548     m_current_connections= stat->m_current_connections;
549     m_total_connections= stat->m_total_connections;
550   }
551 
552   /** Set a table field from the row. */
553   void set_field(uint index, Field *f);
554 };
555 
556 void set_field_object_type(Field *f, enum_object_type object_type);
557 void set_field_lock_type(Field *f, PFS_TL_LOCK_TYPE lock_type);
558 void set_field_mdl_type(Field *f, opaque_mdl_type mdl_type);
559 void set_field_mdl_duration(Field *f, opaque_mdl_duration mdl_duration);
560 void set_field_mdl_status(Field *f, opaque_mdl_status mdl_status);
561 void set_field_isolation_level(Field *f, enum_isolation_level iso_level);
562 void set_field_xa_state(Field *f, enum_xa_transaction_state xa_state);
563 
564 /** Row fragment for socket io statistics columns. */
565 struct PFS_socket_io_stat_row
566 {
567   PFS_byte_stat_row m_read;
568   PFS_byte_stat_row m_write;
569   PFS_byte_stat_row m_misc;
570   PFS_byte_stat_row m_all;
571 
setPFS_socket_io_stat_row572   inline void set(time_normalizer *normalizer, const PFS_socket_io_stat *stat)
573   {
574     PFS_byte_stat all;
575 
576     m_read.set(normalizer, &stat->m_read);
577     m_write.set(normalizer, &stat->m_write);
578     m_misc.set(normalizer, &stat->m_misc);
579 
580     /* Combine stats for all operations */
581     all.aggregate(&stat->m_read);
582     all.aggregate(&stat->m_write);
583     all.aggregate(&stat->m_misc);
584 
585     m_all.set(normalizer, &all);
586   }
587 };
588 
589 /** Row fragment for file io statistics columns. */
590 struct PFS_file_io_stat_row
591 {
592   PFS_byte_stat_row m_read;
593   PFS_byte_stat_row m_write;
594   PFS_byte_stat_row m_misc;
595   PFS_byte_stat_row m_all;
596 
setPFS_file_io_stat_row597   inline void set(time_normalizer *normalizer, const PFS_file_io_stat *stat)
598   {
599     PFS_byte_stat all;
600 
601     m_read.set(normalizer, &stat->m_read);
602     m_write.set(normalizer, &stat->m_write);
603     m_misc.set(normalizer, &stat->m_misc);
604 
605     /* Combine stats for all operations */
606     all.aggregate(&stat->m_read);
607     all.aggregate(&stat->m_write);
608     all.aggregate(&stat->m_misc);
609 
610     m_all.set(normalizer, &all);
611   }
612 };
613 
614 /** Row fragment for memory statistics columns. */
615 struct PFS_memory_stat_row
616 {
617   PFS_memory_stat m_stat;
618 
619   /** Build a row from a memory buffer. */
setPFS_memory_stat_row620   inline void set(const PFS_memory_stat *stat)
621   {
622     m_stat= *stat;
623   }
624 
625   /** Set a table field from the row. */
626   void set_field(uint index, Field *f);
627 };
628 
629 struct PFS_variable_name_row
630 {
631 public:
PFS_variable_name_rowPFS_variable_name_row632   PFS_variable_name_row()
633   {
634     m_str[0]= '\0';
635     m_length= 0;
636   }
637 
638   void make_row(const char* str, size_t length);
639 
640   char m_str[NAME_CHAR_LEN+1];
641   uint m_length;
642 };
643 
644 struct PFS_variable_value_row
645 {
646 public:
647   /** Set the row from a status variable. */
648   void make_row(const Status_variable *var);
649 
650   /** Set the row from a system variable. */
651   void make_row(const System_variable *var);
652 
653   /** Set a table field from the row. */
654   void set_field(Field *f);
655 
656 private:
657   void make_row(const CHARSET_INFO *cs, const char* str, size_t length);
658 
659   char m_str[1024];
660   uint m_length;
661   const CHARSET_INFO *m_charset;
662 };
663 
664 struct PFS_user_variable_value_row
665 {
666 public:
PFS_user_variable_value_rowPFS_user_variable_value_row667   PFS_user_variable_value_row()
668     : m_value(NULL), m_value_length(0)
669   {}
670 
PFS_user_variable_value_rowPFS_user_variable_value_row671   PFS_user_variable_value_row(const PFS_user_variable_value_row& rhs)
672   {
673     make_row(rhs.m_value, rhs.m_value_length);
674   }
675 
~PFS_user_variable_value_rowPFS_user_variable_value_row676   ~PFS_user_variable_value_row()
677   {
678     clear();
679   }
680 
681   void make_row(const char* val, size_t length);
682 
get_valuePFS_user_variable_value_row683   const char *get_value() const
684   { return m_value; }
685 
get_value_lengthPFS_user_variable_value_row686   size_t get_value_length() const
687   { return m_value_length; }
688 
689   void clear();
690 
691 private:
692   char *m_value;
693   size_t m_value_length;
694 };
695 
696 /** @} */
697 
698 #endif
699 
700