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-1335  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_delayed;
353   PFS_stat_row m_write_low_priority;
354   PFS_stat_row m_write_normal;
355   PFS_stat_row m_write_external;
356 
357   /** Build a row from a memory buffer. */
setPFS_table_lock_stat_row358   inline void set(time_normalizer *normalizer, const PFS_table_lock_stat *stat)
359   {
360     PFS_single_stat all_read;
361     PFS_single_stat all_write;
362     PFS_single_stat all;
363 
364     m_read_normal.set(normalizer, & stat->m_stat[PFS_TL_READ]);
365     m_read_with_shared_locks.set(normalizer, & stat->m_stat[PFS_TL_READ_WITH_SHARED_LOCKS]);
366     m_read_high_priority.set(normalizer, & stat->m_stat[PFS_TL_READ_HIGH_PRIORITY]);
367     m_read_no_insert.set(normalizer, & stat->m_stat[PFS_TL_READ_NO_INSERT]);
368     m_read_external.set(normalizer, & stat->m_stat[PFS_TL_READ_EXTERNAL]);
369 
370     all_read.aggregate(& stat->m_stat[PFS_TL_READ]);
371     all_read.aggregate(& stat->m_stat[PFS_TL_READ_WITH_SHARED_LOCKS]);
372     all_read.aggregate(& stat->m_stat[PFS_TL_READ_HIGH_PRIORITY]);
373     all_read.aggregate(& stat->m_stat[PFS_TL_READ_NO_INSERT]);
374     all_read.aggregate(& stat->m_stat[PFS_TL_READ_EXTERNAL]);
375 
376     m_write_allow_write.set(normalizer, & stat->m_stat[PFS_TL_WRITE_ALLOW_WRITE]);
377     m_write_concurrent_insert.set(normalizer, & stat->m_stat[PFS_TL_WRITE_CONCURRENT_INSERT]);
378     m_write_delayed.set(normalizer, & stat->m_stat[PFS_TL_WRITE_DELAYED]);
379     m_write_low_priority.set(normalizer, & stat->m_stat[PFS_TL_WRITE_LOW_PRIORITY]);
380     m_write_normal.set(normalizer, & stat->m_stat[PFS_TL_WRITE]);
381     m_write_external.set(normalizer, & stat->m_stat[PFS_TL_WRITE_EXTERNAL]);
382 
383     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_ALLOW_WRITE]);
384     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_CONCURRENT_INSERT]);
385     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_DELAYED]);
386     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_LOW_PRIORITY]);
387     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE]);
388     all_write.aggregate(& stat->m_stat[PFS_TL_WRITE_EXTERNAL]);
389 
390     all.aggregate(& all_read);
391     all.aggregate(& all_write);
392 
393     m_all_read.set(normalizer, & all_read);
394     m_all_write.set(normalizer, & all_write);
395     m_all.set(normalizer, & all);
396   }
397 };
398 
399 /** Row fragment for stage statistics columns. */
400 struct PFS_stage_stat_row
401 {
402   PFS_stat_row m_timer1_row;
403 
404   /** Build a row from a memory buffer. */
setPFS_stage_stat_row405   inline void set(time_normalizer *normalizer, const PFS_stage_stat *stat)
406   {
407     m_timer1_row.set(normalizer, & stat->m_timer1_stat);
408   }
409 
410   /** Set a table field from the row. */
set_fieldPFS_stage_stat_row411   void set_field(uint index, Field *f)
412   {
413      m_timer1_row.set_field(index, f);
414   }
415 };
416 
417 /** Row fragment for statement statistics columns. */
418 struct PFS_statement_stat_row
419 {
420   PFS_stat_row m_timer1_row;
421   ulonglong m_error_count;
422   ulonglong m_warning_count;
423   ulonglong m_rows_affected;
424   ulonglong m_lock_time;
425   ulonglong m_rows_sent;
426   ulonglong m_rows_examined;
427   ulonglong m_created_tmp_disk_tables;
428   ulonglong m_created_tmp_tables;
429   ulonglong m_select_full_join;
430   ulonglong m_select_full_range_join;
431   ulonglong m_select_range;
432   ulonglong m_select_range_check;
433   ulonglong m_select_scan;
434   ulonglong m_sort_merge_passes;
435   ulonglong m_sort_range;
436   ulonglong m_sort_rows;
437   ulonglong m_sort_scan;
438   ulonglong m_no_index_used;
439   ulonglong m_no_good_index_used;
440 
441   /** Build a row from a memory buffer. */
setPFS_statement_stat_row442   inline void set(time_normalizer *normalizer, const PFS_statement_stat *stat)
443   {
444     if (stat->m_timer1_stat.m_count != 0)
445     {
446       m_timer1_row.set(normalizer, & stat->m_timer1_stat);
447 
448       m_error_count= stat->m_error_count;
449       m_warning_count= stat->m_warning_count;
450       m_lock_time= stat->m_lock_time * MICROSEC_TO_PICOSEC;
451       m_rows_affected= stat->m_rows_affected;
452       m_rows_sent= stat->m_rows_sent;
453       m_rows_examined= stat->m_rows_examined;
454       m_created_tmp_disk_tables= stat->m_created_tmp_disk_tables;
455       m_created_tmp_tables= stat->m_created_tmp_tables;
456       m_select_full_join= stat->m_select_full_join;
457       m_select_full_range_join= stat->m_select_full_range_join;
458       m_select_range= stat->m_select_range;
459       m_select_range_check= stat->m_select_range_check;
460       m_select_scan= stat->m_select_scan;
461       m_sort_merge_passes= stat->m_sort_merge_passes;
462       m_sort_range= stat->m_sort_range;
463       m_sort_rows= stat->m_sort_rows;
464       m_sort_scan= stat->m_sort_scan;
465       m_no_index_used= stat->m_no_index_used;
466       m_no_good_index_used= stat->m_no_good_index_used;
467     }
468     else
469     {
470       m_timer1_row.reset();
471 
472       m_error_count= 0;
473       m_warning_count= 0;
474       m_lock_time= 0;
475       m_rows_affected= 0;
476       m_rows_sent= 0;
477       m_rows_examined= 0;
478       m_created_tmp_disk_tables= 0;
479       m_created_tmp_tables= 0;
480       m_select_full_join= 0;
481       m_select_full_range_join= 0;
482       m_select_range= 0;
483       m_select_range_check= 0;
484       m_select_scan= 0;
485       m_sort_merge_passes= 0;
486       m_sort_range= 0;
487       m_sort_rows= 0;
488       m_sort_scan= 0;
489       m_no_index_used= 0;
490       m_no_good_index_used= 0;
491     }
492   }
493 
494   /** Set a table field from the row. */
495   void set_field(uint index, Field *f);
496 };
497 
498 /** Row fragment for stored program statistics. */
499 struct PFS_sp_stat_row
500 {
501   PFS_stat_row m_timer1_row;
502 
503   /** Build a row from a memory buffer. */
setPFS_sp_stat_row504   inline void set(time_normalizer *normalizer, const PFS_sp_stat *stat)
505   {
506     m_timer1_row.set(normalizer, & stat->m_timer1_stat);
507   }
508 
509   /** Set a table field from the row. */
set_fieldPFS_sp_stat_row510   inline void set_field(uint index, Field *f)
511   {
512     m_timer1_row.set_field(index, f);
513   }
514 };
515 
516 /** Row fragment for transaction statistics columns. */
517 struct PFS_transaction_stat_row
518 {
519   PFS_stat_row m_timer1_row;
520   PFS_stat_row m_read_write_row;
521   PFS_stat_row m_read_only_row;
522   ulonglong m_savepoint_count;
523   ulonglong m_rollback_to_savepoint_count;
524   ulonglong m_release_savepoint_count;
525 
526   /** Build a row from a memory buffer. */
setPFS_transaction_stat_row527   inline void set(time_normalizer *normalizer, const PFS_transaction_stat *stat)
528   {
529     /* Combine read write/read only stats */
530     PFS_single_stat all;
531     all.aggregate(&stat->m_read_only_stat);
532     all.aggregate(&stat->m_read_write_stat);
533 
534     m_timer1_row.set(normalizer, &all);
535     m_read_write_row.set(normalizer, &stat->m_read_write_stat);
536     m_read_only_row.set(normalizer, &stat->m_read_only_stat);
537   }
538 
539   /** Set a table field from the row. */
540   void set_field(uint index, Field *f);
541 };
542 
543 /** Row fragment for connection statistics. */
544 struct PFS_connection_stat_row
545 {
546   ulonglong m_current_connections;
547   ulonglong m_total_connections;
548 
setPFS_connection_stat_row549   inline void set(const PFS_connection_stat *stat)
550   {
551     m_current_connections= stat->m_current_connections;
552     m_total_connections= stat->m_total_connections;
553   }
554 
555   /** Set a table field from the row. */
556   void set_field(uint index, Field *f);
557 };
558 
559 void set_field_object_type(Field *f, enum_object_type object_type);
560 void set_field_lock_type(Field *f, PFS_TL_LOCK_TYPE lock_type);
561 void set_field_mdl_type(Field *f, opaque_mdl_type mdl_type, bool backup);
562 void set_field_mdl_duration(Field *f, opaque_mdl_duration mdl_duration);
563 void set_field_mdl_status(Field *f, opaque_mdl_status mdl_status);
564 void set_field_isolation_level(Field *f, enum_isolation_level iso_level);
565 void set_field_xa_state(Field *f, enum_xa_transaction_state xa_state);
566 
567 /** Row fragment for socket io statistics columns. */
568 struct PFS_socket_io_stat_row
569 {
570   PFS_byte_stat_row m_read;
571   PFS_byte_stat_row m_write;
572   PFS_byte_stat_row m_misc;
573   PFS_byte_stat_row m_all;
574 
setPFS_socket_io_stat_row575   inline void set(time_normalizer *normalizer, const PFS_socket_io_stat *stat)
576   {
577     PFS_byte_stat all;
578 
579     m_read.set(normalizer, &stat->m_read);
580     m_write.set(normalizer, &stat->m_write);
581     m_misc.set(normalizer, &stat->m_misc);
582 
583     /* Combine stats for all operations */
584     all.aggregate(&stat->m_read);
585     all.aggregate(&stat->m_write);
586     all.aggregate(&stat->m_misc);
587 
588     m_all.set(normalizer, &all);
589   }
590 };
591 
592 /** Row fragment for file io statistics columns. */
593 struct PFS_file_io_stat_row
594 {
595   PFS_byte_stat_row m_read;
596   PFS_byte_stat_row m_write;
597   PFS_byte_stat_row m_misc;
598   PFS_byte_stat_row m_all;
599 
setPFS_file_io_stat_row600   inline void set(time_normalizer *normalizer, const PFS_file_io_stat *stat)
601   {
602     PFS_byte_stat all;
603 
604     m_read.set(normalizer, &stat->m_read);
605     m_write.set(normalizer, &stat->m_write);
606     m_misc.set(normalizer, &stat->m_misc);
607 
608     /* Combine stats for all operations */
609     all.aggregate(&stat->m_read);
610     all.aggregate(&stat->m_write);
611     all.aggregate(&stat->m_misc);
612 
613     m_all.set(normalizer, &all);
614   }
615 };
616 
617 /** Row fragment for memory statistics columns. */
618 struct PFS_memory_stat_row
619 {
620   PFS_memory_stat m_stat;
621 
622   /** Build a row from a memory buffer. */
setPFS_memory_stat_row623   inline void set(const PFS_memory_stat *stat)
624   {
625     m_stat= *stat;
626   }
627 
628   /** Set a table field from the row. */
629   void set_field(uint index, Field *f);
630 };
631 
632 struct PFS_variable_name_row
633 {
634 public:
PFS_variable_name_rowPFS_variable_name_row635   PFS_variable_name_row()
636   {
637     m_str[0]= '\0';
638     m_length= 0;
639   }
640 
641   void make_row(const char* str, size_t length);
642 
643   char m_str[NAME_CHAR_LEN+1];
644   uint m_length;
645 };
646 
647 struct PFS_variable_value_row
648 {
649 public:
650   /** Set the row from a status variable. */
651   void make_row(const Status_variable *var);
652 
653   /** Set the row from a system variable. */
654   void make_row(const System_variable *var);
655 
656   /** Set a table field from the row. */
657   void set_field(Field *f);
658 
659 private:
660   void make_row(const CHARSET_INFO *cs, const char* str, size_t length);
661 
662   char m_str[1024];
663   uint m_length;
664   const CHARSET_INFO *m_charset;
665 };
666 
667 struct PFS_user_variable_value_row
668 {
669 public:
PFS_user_variable_value_rowPFS_user_variable_value_row670   PFS_user_variable_value_row()
671     : m_value(NULL), m_value_length(0)
672   {}
673 
PFS_user_variable_value_rowPFS_user_variable_value_row674   PFS_user_variable_value_row(const PFS_user_variable_value_row& rhs)
675   {
676     make_row(rhs.m_value, rhs.m_value_length);
677   }
678 
~PFS_user_variable_value_rowPFS_user_variable_value_row679   ~PFS_user_variable_value_row()
680   {
681     clear();
682   }
683 
684   void make_row(const char* val, size_t length);
685 
get_valuePFS_user_variable_value_row686   const char *get_value() const
687   { return m_value; }
688 
get_value_lengthPFS_user_variable_value_row689   size_t get_value_length() const
690   { return m_value_length; }
691 
692   void clear();
693 
694 private:
695   char *m_value;
696   size_t m_value_length;
697 };
698 
699 /** @} */
700 
701 #endif
702 
703