~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/info_schema/info_schema.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-08-08 04:22:33 UTC
  • mto: (1115.3.4 captain)
  • mto: This revision was merged to the branch mainline in revision 1117.
  • Revision ID: osullivan.padraig@gmail.com-20090808042233-q0z88zc490z3f3r7
Renamed the Command class to be Statement. Renamed the command directory to
statement and also the command header file to statement. Updated various
source files to reflect this renaming.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2009 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
/**
 
22
 * @file 
 
23
 *   I_S plugin implementation.
 
24
 */
 
25
 
 
26
#include <drizzled/server_includes.h>
 
27
#include <drizzled/session.h>
 
28
#include <drizzled/show.h>
 
29
 
 
30
#include "info_schema_methods.h"
 
31
#include "info_schema_columns.h"
 
32
 
 
33
#include <vector>
 
34
 
 
35
using namespace std;
 
36
 
 
37
/*
 
38
 * Vectors of columns for various I_S tables.
 
39
 */
 
40
static vector<const ColumnInfo *> char_set_columns;
 
41
static vector<const ColumnInfo *> collation_columns;
 
42
static vector<const ColumnInfo *> coll_char_columns;
 
43
static vector<const ColumnInfo *> col_columns;
 
44
static vector<const ColumnInfo *> key_col_usage_columns;
 
45
static vector<const ColumnInfo *> open_tab_columns;
 
46
static vector<const ColumnInfo *> plugin_columns;
 
47
static vector<const ColumnInfo *> processlist_columns;
 
48
static vector<const ColumnInfo *> ref_constraint_columns;
 
49
static vector<const ColumnInfo *> schemata_columns;
 
50
static vector<const ColumnInfo *> stats_columns;
 
51
static vector<const ColumnInfo *> status_columns;
 
52
static vector<const ColumnInfo *> tab_constraints_columns;
 
53
static vector<const ColumnInfo *> tables_columns;
 
54
static vector<const ColumnInfo *> tab_names_columns;
 
55
 
 
56
/*
 
57
 * Methods for various I_S tables.
 
58
 */
 
59
static InfoSchemaMethods *char_set_methods= NULL;
 
60
static InfoSchemaMethods *collation_methods= NULL;
 
61
static InfoSchemaMethods *coll_char_methods= NULL;
 
62
static InfoSchemaMethods *columns_methods= NULL;
 
63
static InfoSchemaMethods *key_col_usage_methods= NULL;
 
64
static InfoSchemaMethods *open_tab_methods= NULL;
 
65
static InfoSchemaMethods *plugins_methods= NULL;
 
66
static InfoSchemaMethods *processlist_methods= NULL;
 
67
static InfoSchemaMethods *ref_constraint_methods= NULL;
 
68
static InfoSchemaMethods *schemata_methods= NULL;
 
69
static InfoSchemaMethods *stats_methods= NULL;
 
70
static InfoSchemaMethods *status_methods= NULL;
 
71
static InfoSchemaMethods *tab_constraints_methods= NULL;
 
72
static InfoSchemaMethods *tables_methods= NULL;
 
73
static InfoSchemaMethods *tab_names_methods= NULL;
 
74
static InfoSchemaMethods *variables_methods= NULL;
 
75
 
 
76
/*
 
77
 * I_S tables.
 
78
 */
 
79
static InfoSchemaTable *char_set_table= NULL;
 
80
static InfoSchemaTable *collation_table= NULL;
 
81
static InfoSchemaTable *coll_char_set_table= NULL;
 
82
static InfoSchemaTable *columns_table= NULL;
 
83
static InfoSchemaTable *key_col_usage_table= NULL;
 
84
static InfoSchemaTable *global_stat_table= NULL;
 
85
static InfoSchemaTable *global_var_table= NULL;
 
86
static InfoSchemaTable *open_tab_table= NULL;
 
87
static InfoSchemaTable *plugins_table= NULL;
 
88
static InfoSchemaTable *processlist_table= NULL;
 
89
static InfoSchemaTable *ref_constraint_table= NULL;
 
90
static InfoSchemaTable *schemata_table= NULL;
 
91
static InfoSchemaTable *sess_stat_table= NULL;
 
92
static InfoSchemaTable *sess_var_table= NULL;
 
93
static InfoSchemaTable *stats_table= NULL;
 
94
static InfoSchemaTable *status_table= NULL;
 
95
static InfoSchemaTable *tab_constraints_table= NULL;
 
96
static InfoSchemaTable *tables_table= NULL;
 
97
static InfoSchemaTable *tab_names_table= NULL;
 
98
static InfoSchemaTable *var_table= NULL;
 
99
 
 
100
/**
 
101
 * Populate the vectors of columns for each I_S table.
 
102
 *
 
103
 * @return false on success; true on failure.
 
104
 */
 
105
static bool initTableColumns()
 
106
{
 
107
  bool retval= false;
 
108
 
 
109
  if ((retval= createCharSetColumns(char_set_columns)) == true)
 
110
  {
 
111
    return true;
 
112
  }
 
113
 
 
114
  if ((retval= createCollationColumns(collation_columns)) == true)
 
115
  {
 
116
    return true;
 
117
  }
 
118
 
 
119
  if ((retval= createCollCharSetColumns(coll_char_columns)) == true)
 
120
  {
 
121
    return true;
 
122
  }
 
123
 
 
124
  if ((retval= createColColumns(col_columns)) == true)
 
125
  {
 
126
    return true;
 
127
  }
 
128
 
 
129
  if ((retval= createKeyColUsageColumns(key_col_usage_columns)) == true)
 
130
  {
 
131
    return true;
 
132
  }
 
133
 
 
134
  if ((retval= createOpenTabColumns(open_tab_columns)) == true)
 
135
  {
 
136
    return true;
 
137
  }
 
138
 
 
139
  if ((retval= createPluginsColumns(plugin_columns)) == true)
 
140
  {
 
141
    return true;
 
142
  }
 
143
 
 
144
  if ((retval= createProcessListColumns(processlist_columns)) == true)
 
145
  {
 
146
    return true;
 
147
  }
 
148
 
 
149
  if ((retval= createRefConstraintColumns(ref_constraint_columns)) == true)
 
150
  {
 
151
    return true;
 
152
  }
 
153
 
 
154
  if ((retval= createSchemataColumns(schemata_columns)) == true)
 
155
  {
 
156
    return true;
 
157
  }
 
158
 
 
159
  if ((retval= createStatsColumns(stats_columns)) == true)
 
160
  {
 
161
    return true;
 
162
  }
 
163
 
 
164
  if ((retval= createStatusColumns(status_columns)) == true)
 
165
  {
 
166
    return true;
 
167
  }
 
168
 
 
169
  if ((retval= createTabConstraintsColumns(tab_constraints_columns)) == true)
 
170
  {
 
171
    return true;
 
172
  }
 
173
 
 
174
  if ((retval= createTablesColumns(tables_columns)) == true)
 
175
  {
 
176
    return true;
 
177
  }
 
178
 
 
179
  if ((retval= createTabNamesColumns(tab_names_columns)) == true)
 
180
  {
 
181
    return true;
 
182
  }
 
183
 
 
184
  return false;
 
185
}
 
186
 
 
187
/**
 
188
 * Clear the vectors of columns for each I_S table.
 
189
 */
 
190
static void cleanupTableColumns()
 
191
{
 
192
  clearColumns(char_set_columns);
 
193
  clearColumns(collation_columns);
 
194
  clearColumns(coll_char_columns);
 
195
  clearColumns(col_columns);
 
196
  clearColumns(key_col_usage_columns);
 
197
  clearColumns(open_tab_columns);
 
198
  clearColumns(plugin_columns);
 
199
  clearColumns(processlist_columns);
 
200
  clearColumns(ref_constraint_columns);
 
201
  clearColumns(schemata_columns);
 
202
  clearColumns(stats_columns);
 
203
  clearColumns(status_columns);
 
204
  clearColumns(tab_constraints_columns);
 
205
  clearColumns(tables_columns);
 
206
  clearColumns(tab_names_columns);
 
207
}
 
208
 
 
209
/**
 
210
 * Initialize the methods for each I_S table.
 
211
 *
 
212
 * @return false on success; true on failure
 
213
 */
 
214
static bool initTableMethods()
 
215
{
 
216
  if ((char_set_methods= new(std::nothrow) CharSetISMethods()) == NULL)
 
217
  {
 
218
    return true;
 
219
  }
 
220
 
 
221
  if ((collation_methods= new(std::nothrow) CollationISMethods()) == NULL)
 
222
  {
 
223
    return true;
 
224
  }
 
225
 
 
226
  if ((coll_char_methods= new(std::nothrow) CollCharISMethods()) == NULL)
 
227
  {
 
228
    return true;
 
229
  }
 
230
 
 
231
  if ((columns_methods= new(std::nothrow) ColumnsISMethods()) == NULL)
 
232
  {
 
233
    return true;
 
234
  }
 
235
 
 
236
  if ((key_col_usage_methods= new(std::nothrow) KeyColUsageISMethods()) == NULL)
 
237
  {
 
238
    return true;
 
239
  }
 
240
 
 
241
  if ((open_tab_methods= new(std::nothrow) OpenTablesISMethods()) == NULL)
 
242
  {
 
243
    return true;
 
244
  }
 
245
 
 
246
  if ((plugins_methods= new(std::nothrow) PluginsISMethods()) == NULL)
 
247
  {
 
248
    return true;
 
249
  }
 
250
 
 
251
  if ((processlist_methods= new(std::nothrow) ProcessListISMethods()) == NULL)
 
252
  {
 
253
    return true;
 
254
  }
 
255
 
 
256
  if ((ref_constraint_methods= new(std::nothrow) RefConstraintsISMethods()) == NULL)
 
257
  {
 
258
    return true;
 
259
  }
 
260
 
 
261
  if ((schemata_methods= new(std::nothrow) SchemataISMethods()) == NULL)
 
262
  {
 
263
    return true;
 
264
  }
 
265
 
 
266
  if ((stats_methods= new(std::nothrow) StatsISMethods()) == NULL)
 
267
  {
 
268
    return true;
 
269
  }
 
270
 
 
271
  if ((status_methods= new(std::nothrow) StatusISMethods()) == NULL)
 
272
  {
 
273
    return true;
 
274
  }
 
275
 
 
276
  if ((tab_constraints_methods= new(std::nothrow) TabConstraintsISMethods()) == NULL)
 
277
  {
 
278
    return true;
 
279
  }
 
280
 
 
281
  if ((tables_methods= new(std::nothrow) TablesISMethods()) == NULL)
 
282
  {
 
283
    return true;
 
284
  }
 
285
 
 
286
  if ((tab_names_methods= new(std::nothrow) TabNamesISMethods()) == NULL)
 
287
  {
 
288
    return true;
 
289
  }
 
290
 
 
291
  if ((variables_methods= new(std::nothrow) VariablesISMethods()) == NULL)
 
292
  {
 
293
    return true;
 
294
  }
 
295
 
 
296
  return false;
 
297
}
 
298
 
 
299
/**
 
300
 * Delete memory allocated for the I_S table methods.
 
301
 */
 
302
static void cleanupTableMethods()
 
303
{
 
304
  delete char_set_methods;
 
305
  delete collation_methods;
 
306
  delete coll_char_methods;
 
307
  delete columns_methods;
 
308
  delete key_col_usage_methods;
 
309
  delete open_tab_methods;
 
310
  delete plugins_methods;
 
311
  delete processlist_methods;
 
312
  delete ref_constraint_methods;
 
313
  delete schemata_methods;
 
314
  delete stats_methods;
 
315
  delete status_methods;
 
316
  delete tab_constraints_methods;
 
317
  delete tables_methods;
 
318
  delete tab_names_methods;
 
319
  delete variables_methods;
 
320
}
 
321
 
 
322
/**
 
323
 * Initialize the I_S tables.
 
324
 *
 
325
 * @return false on success; true on failure
 
326
 */
 
327
static bool initTables()
 
328
{
 
329
 
 
330
  char_set_table= new(std::nothrow) InfoSchemaTable("CHARACTER_SETS",
 
331
                                                    char_set_columns,
 
332
                                                    -1, -1, false, false, 0,
 
333
                                                    char_set_methods);
 
334
  if (char_set_table == NULL)
 
335
  {
 
336
    return true;
 
337
  }
 
338
 
 
339
  collation_table= new(std::nothrow) InfoSchemaTable("COLLATIONS",
 
340
                                                     collation_columns,
 
341
                                                     -1, -1, false, false, 0,
 
342
                                                     collation_methods);
 
343
  if (collation_table == NULL)
 
344
  {
 
345
    return true;
 
346
  }
 
347
 
 
348
  coll_char_set_table= new(std::nothrow) InfoSchemaTable("COLLATION_CHARACTER_SET_APPLICABILITY",
 
349
                                                         coll_char_columns,
 
350
                                                         -1, -1, false, false, 0,
 
351
                                                         coll_char_methods);
 
352
  if (coll_char_set_table == NULL)
 
353
  {
 
354
    return true;
 
355
  }
 
356
 
 
357
  columns_table= new(std::nothrow) InfoSchemaTable("COLUMNS",
 
358
                                                   col_columns,
 
359
                                                   1, 2, false, true,
 
360
                                                   OPTIMIZE_I_S_TABLE,
 
361
                                                   columns_methods);
 
362
  if (columns_table == NULL)
 
363
  {
 
364
    return true;
 
365
  }
 
366
 
 
367
  key_col_usage_table= new(std::nothrow) InfoSchemaTable("KEY_COLUMN_USAGE",
 
368
                                                         key_col_usage_columns,
 
369
                                                         4, 5, false, true,
 
370
                                                         OPEN_TABLE_ONLY,
 
371
                                                         key_col_usage_methods);
 
372
  if (key_col_usage_table == NULL)
 
373
  {
 
374
    return true;
 
375
  }
 
376
 
 
377
  global_stat_table= new(std::nothrow) InfoSchemaTable("GLOBAL_STATUS",
 
378
                                                       status_columns,
 
379
                                                       -1, -1, false, false,
 
380
                                                       0, status_methods);
 
381
  if (global_stat_table == NULL)
 
382
  {
 
383
    return true;
 
384
  }
 
385
 
 
386
  global_var_table= new(std::nothrow) InfoSchemaTable("GLOBAL_VARIABLES",
 
387
                                                      status_columns,
 
388
                                                      -1, -1, false, false,
 
389
                                                      0, variables_methods);
 
390
  if (global_var_table == NULL)
 
391
  {
 
392
    return true;
 
393
  }
 
394
  
 
395
  open_tab_table= new(std::nothrow) InfoSchemaTable("OPEN_TABLES",
 
396
                                                    open_tab_columns,
 
397
                                                    -1, -1, true, false, 0,
 
398
                                                    open_tab_methods);
 
399
  if (open_tab_table == NULL)
 
400
  {
 
401
    return true;
 
402
  }
 
403
 
 
404
  plugins_table= new(std::nothrow) InfoSchemaTable("PLUGINS",
 
405
                                                   plugin_columns,
 
406
                                                   -1, -1, false, false, 0,
 
407
                                                   plugins_methods);
 
408
  if (plugins_table == NULL)
 
409
  {
 
410
    return true;
 
411
  }
 
412
 
 
413
  processlist_table= new(std::nothrow) InfoSchemaTable("PROCESSLIST",
 
414
                                                       processlist_columns,
 
415
                                                       -1, -1, false, false, 0,
 
416
                                                       processlist_methods);
 
417
  if (processlist_table == NULL)
 
418
  {
 
419
    return true;
 
420
  }
 
421
 
 
422
  ref_constraint_table= new(std::nothrow) InfoSchemaTable("REFERENTIAL_CONSTRAINTS",
 
423
                                                          ref_constraint_columns,
 
424
                                                          1, 9, false, true,
 
425
                                                          OPEN_TABLE_ONLY,
 
426
                                                          ref_constraint_methods);
 
427
  if (ref_constraint_table == NULL)
 
428
  {
 
429
    return true;
 
430
  }
 
431
 
 
432
  schemata_table= new(std::nothrow) InfoSchemaTable("SCHEMATA",
 
433
                                                    schemata_columns,
 
434
                                                    1, -1, false, false, 0,
 
435
                                                    schemata_methods);
 
436
  if (schemata_table == NULL)
 
437
  {
 
438
    return true;
 
439
  }
 
440
 
 
441
  sess_stat_table= new(std::nothrow) InfoSchemaTable("SESSION_STATUS",
 
442
                                                     status_columns,
 
443
                                                     -1, -1, false, false,
 
444
                                                     0, status_methods);
 
445
  if (sess_stat_table == NULL)
 
446
  {
 
447
    return true;
 
448
  }
 
449
 
 
450
  sess_var_table= new(std::nothrow) InfoSchemaTable("SESSION_VARIABLES",
 
451
                                                    status_columns,
 
452
                                                    -1, -1, false, false, 0,
 
453
                                                    variables_methods);
 
454
  if (sess_var_table == NULL)
 
455
  {
 
456
    return true;
 
457
  }
 
458
 
 
459
  stats_table= new(std::nothrow) InfoSchemaTable("STATISTICS",
 
460
                                                 stats_columns,
 
461
                                                 1, 2, false, true,
 
462
                                                 OPEN_TABLE_ONLY | OPTIMIZE_I_S_TABLE,
 
463
                                                 stats_methods);
 
464
  if (stats_table == NULL)
 
465
  {
 
466
    return true;
 
467
  }
 
468
 
 
469
  status_table= new(std::nothrow) InfoSchemaTable("STATUS",
 
470
                                                  status_columns,
 
471
                                                  -1, -1, true, false, 0,
 
472
                                                  status_methods);
 
473
  if (status_table == NULL)
 
474
  {
 
475
    return true;
 
476
  }
 
477
 
 
478
  tab_constraints_table= new(std::nothrow) InfoSchemaTable("TABLE_CONSTRAINTS",
 
479
                                                           tab_constraints_columns,
 
480
                                                           3, 4, false, true,
 
481
                                                           OPEN_TABLE_ONLY,
 
482
                                                           tab_constraints_methods);
 
483
  if (tab_constraints_table == NULL)
 
484
  {
 
485
    return true;
 
486
  }
 
487
 
 
488
  tables_table= new(std::nothrow) InfoSchemaTable("TABLES",
 
489
                                                  tables_columns,
 
490
                                                  1, 2, false, true,
 
491
                                                  OPTIMIZE_I_S_TABLE,
 
492
                                                  tables_methods);
 
493
  if (tables_table == NULL)
 
494
  {
 
495
    return true;
 
496
  }
 
497
 
 
498
  tab_names_table= new(std::nothrow) InfoSchemaTable("TABLE_NAMES",
 
499
                                                     tab_names_columns,
 
500
                                                     1, 2, true, true, 0,
 
501
                                                     tab_names_methods);
 
502
  if (tab_names_table == NULL)
 
503
  {
 
504
    return true;
 
505
  }
 
506
 
 
507
  var_table= new(std::nothrow) InfoSchemaTable("VARIABLES",
 
508
                                               status_columns,
 
509
                                               -1, -1, true, false, 0,
 
510
                                               variables_methods);
 
511
  if (var_table == NULL)
 
512
  {
 
513
    return true;
 
514
  }
 
515
 
 
516
  return false;
 
517
}
 
518
 
 
519
/**
 
520
 * Delete memory allocated for the I_S tables.
 
521
 */
 
522
static void cleanupTables()
 
523
{
 
524
  delete char_set_table;
 
525
  delete collation_table;
 
526
  delete coll_char_set_table;
 
527
  delete columns_table;
 
528
  delete key_col_usage_table;
 
529
  delete global_stat_table;
 
530
  delete global_var_table;
 
531
  delete open_tab_table;
 
532
  delete plugins_table;
 
533
  delete processlist_table;
 
534
  delete ref_constraint_table;
 
535
  delete schemata_table;
 
536
  delete sess_stat_table;
 
537
  delete sess_var_table;
 
538
  delete stats_table;
 
539
  delete status_table;
 
540
  delete tab_constraints_table;
 
541
  delete tables_table;
 
542
  delete tab_names_table;
 
543
  delete var_table;
 
544
}
 
545
 
 
546
/**
 
547
 * Initialize the I_S plugin.
 
548
 *
 
549
 * @param[in] registry the PluginRegistry singleton
 
550
 * @return 0 on success; 1 on failure.
 
551
 */
 
552
static int infoSchemaInit(PluginRegistry& registry)
 
553
{
 
554
  bool retval= false;
 
555
 
 
556
  if ((retval= initTableMethods()) == true)
 
557
  {
 
558
    return 1;
 
559
  }
 
560
 
 
561
  if ((retval= initTableColumns()) == true)
 
562
  {
 
563
    return 1;
 
564
  }
 
565
 
 
566
  if ((retval= initTables()) == true)
 
567
  {
 
568
    return 1;
 
569
  }
 
570
 
 
571
  registry.add(char_set_table);
 
572
  registry.add(collation_table);
 
573
  registry.add(coll_char_set_table);
 
574
  registry.add(columns_table);
 
575
  registry.add(key_col_usage_table);
 
576
  registry.add(global_stat_table);
 
577
  registry.add(global_var_table);
 
578
  registry.add(open_tab_table);
 
579
  registry.add(plugins_table);
 
580
  registry.add(processlist_table);
 
581
  registry.add(ref_constraint_table);
 
582
  registry.add(schemata_table);
 
583
  registry.add(sess_stat_table);
 
584
  registry.add(sess_var_table);
 
585
  registry.add(stats_table);
 
586
  registry.add(status_table);
 
587
  registry.add(tab_constraints_table);
 
588
  registry.add(tables_table);
 
589
  registry.add(tab_names_table);
 
590
  registry.add(var_table);
 
591
 
 
592
  return 0;
 
593
}
 
594
 
 
595
/**
 
596
 * Clean up the I_S plugin.
 
597
 *
 
598
 * @param[in] registry the PluginRegistry singleton
 
599
 * @return 0 on success; 1 on failure
 
600
 */
 
601
static int infoSchemaDone(PluginRegistry& registry)
 
602
{
 
603
  registry.remove(char_set_table);
 
604
  registry.remove(collation_table);
 
605
  registry.remove(coll_char_set_table);
 
606
  registry.remove(columns_table);
 
607
  registry.remove(key_col_usage_table);
 
608
  registry.remove(global_stat_table);
 
609
  registry.remove(global_var_table);
 
610
  registry.remove(open_tab_table);
 
611
  registry.remove(plugins_table);
 
612
  registry.remove(processlist_table);
 
613
  registry.remove(ref_constraint_table);
 
614
  registry.remove(schemata_table);
 
615
  registry.remove(sess_stat_table);
 
616
  registry.remove(sess_var_table);
 
617
  registry.remove(stats_table);
 
618
  registry.remove(status_table);
 
619
  registry.remove(tab_constraints_table);
 
620
  registry.remove(tables_table);
 
621
  registry.remove(tab_names_table);
 
622
  registry.remove(var_table);
 
623
 
 
624
  cleanupTableMethods();
 
625
  cleanupTableColumns();
 
626
  cleanupTables();
 
627
 
 
628
  return 0;
 
629
}
 
630
 
 
631
drizzle_declare_plugin(info_schema)
 
632
{
 
633
  "info_schema",
 
634
  "0.1",
 
635
  "Padraig O'Sullivan",
 
636
  "I_S plugin",
 
637
  PLUGIN_LICENSE_GPL,
 
638
  infoSchemaInit,
 
639
  infoSchemaDone,
 
640
  NULL,
 
641
  NULL,
 
642
  NULL
 
643
}
 
644
drizzle_declare_plugin_end;