12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
17
/* Copy data from a textfile to table */
19
19
#include "config.h"
21
20
#include <drizzled/sql_load.h>
22
21
#include <drizzled/error.h>
23
22
#include <drizzled/data_home.h>
24
23
#include <drizzled/session.h>
25
24
#include <drizzled/sql_base.h>
26
#include <drizzled/field/epoch.h>
25
#include <drizzled/field/timestamp.h>
27
26
#include "drizzled/internal/my_sys.h"
28
27
#include "drizzled/internal/iocache.h"
29
28
#include <drizzled/db.h>
30
#include "drizzled/plugin/storage_engine.h"
32
30
#include <sys/stat.h>
34
32
#include <algorithm>
36
#include <boost/filesystem.hpp>
38
namespace fs=boost::filesystem;
39
35
using namespace std;
78
74
void end_io_cache()
76
internal::end_io_cache(&cache);
81
77
need_end_io_cache = 0;
85
81
Either this method, or we need to make cache public
86
Arg must be set from load() since constructor does not see
82
Arg must be set from mysql_load() since constructor does not see
87
83
either the table or Session value
89
85
void set_io_cache_arg(void* arg) { cache.arg = arg; }
92
static int read_fixed_length(Session *session, CopyInfo &info, TableList *table_list,
88
static int read_fixed_length(Session *session, COPY_INFO &info, TableList *table_list,
93
89
List<Item> &fields_vars, List<Item> &set_fields,
94
90
List<Item> &set_values, READ_INFO &read_info,
95
91
uint32_t skip_lines,
96
92
bool ignore_check_option_errors);
97
static int read_sep_field(Session *session, CopyInfo &info, TableList *table_list,
93
static int read_sep_field(Session *session, COPY_INFO &info, TableList *table_list,
98
94
List<Item> &fields_vars, List<Item> &set_fields,
99
95
List<Item> &set_values, READ_INFO &read_info,
100
96
String &enclosed, uint32_t skip_lines,
121
117
true - error / false - success
124
int load(Session *session,file_exchange *ex,TableList *table_list,
120
int mysql_load(Session *session,file_exchange *ex,TableList *table_list,
125
121
List<Item> &fields_vars, List<Item> &set_fields,
126
122
List<Item> &set_values,
127
123
enum enum_duplicates handle_duplicates, bool ignore)
125
char name[FN_REFLEN];
130
127
Table *table= NULL;
132
129
String *field_term=ex->field_term,*escaped=ex->escaped;
133
130
String *enclosed=ex->enclosed;
136
assert(table_list->getSchemaName()); // This should never be null
132
char *db= table_list->db; // This is never null
139
135
If path for cursor is not defined, we will use the current database.
140
136
If this is not set, we will use the directory where the table to be
141
137
loaded is located
143
util::string::const_shared_ptr schema(session->schema());
144
const char *tdb= (schema and not schema->empty()) ? schema->c_str() : table_list->getSchemaName(); // Result should never be null
139
const char *tdb= session->db.empty() ? db : session->db.c_str(); // Result is never null
146
141
uint32_t skip_lines= ex->skip_lines;
147
142
bool transactional_table;
148
Session::killed_state_t killed_status= Session::NOT_KILLED;
143
Session::killed_state killed_status= Session::NOT_KILLED;
150
145
/* Escape and enclosed character may be a utf8 4-byte character */
151
146
if (escaped->length() > 4 || enclosed->length() > 4)
262
fs::path to_file(ex->file_name);
263
fs::path target_path(fs::system_complete(getDataHomeCatalog()));
264
if (not to_file.has_root_directory())
266
int count_elements= 0;
267
for (fs::path::iterator iter= to_file.begin();
268
iter != to_file.end();
269
++iter, ++count_elements)
272
if (count_elements == 1)
276
target_path /= to_file;
280
target_path= to_file;
283
if (not secure_file_priv.string().empty())
285
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
287
/* Read only allowed from within dir specified by secure_file_priv */
288
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
256
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
257
ex->file_name+=dirname_length(ex->file_name);
259
if (!internal::dirname_length(ex->file_name))
261
strcpy(name, drizzle_real_data_home);
262
strncat(name, tdb, FN_REFLEN-strlen(drizzle_real_data_home)-1);
263
(void) internal::fn_format(name, ex->file_name, name, "",
264
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
268
(void) internal::fn_format(name, ex->file_name, drizzle_real_data_home, "",
269
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
271
if (opt_secure_file_priv &&
272
strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
274
/* Read only allowed from within dir specified by secure_file_priv */
275
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
279
struct stat stat_info;
280
if (stat(name,&stat_info))
282
my_error(ER_FILE_NOT_FOUND, MYF(0), name, errno);
286
// if we are not in slave thread, the cursor must be:
287
if (!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
288
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
289
((stat_info.st_mode & S_IFREG) == S_IFREG ||
290
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
292
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
295
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
298
if ((file=internal::my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
300
my_error(ER_CANT_OPEN_FILE, MYF(0), name, errno);
293
struct stat stat_info;
294
if (stat(target_path.file_string().c_str(), &stat_info))
296
my_error(ER_FILE_NOT_FOUND, MYF(0), target_path.file_string().c_str(), errno);
300
// if we are not in slave thread, the cursor must be:
301
if (!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
302
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
303
((stat_info.st_mode & S_IFREG) == S_IFREG ||
304
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
306
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), target_path.file_string().c_str());
309
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
313
if ((file=internal::my_open(target_path.file_string().c_str(), O_RDONLY,MYF(MY_WME))) < 0)
315
my_error(ER_CANT_OPEN_FILE, MYF(0), target_path.file_string().c_str(), errno);
319
306
memset(&info, 0, sizeof(info));
320
307
info.ignore= ignore;
321
308
info.handle_duplicates=handle_duplicates;
322
309
info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
324
identifier::Schema identifier(*schema);
325
311
READ_INFO read_info(file, tot_length,
326
ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(identifier),
327
*field_term, *ex->line_start, *ex->line_term, *enclosed,
312
ex->cs ? ex->cs : get_default_db_collation(session->db.c_str()),
313
*field_term,*ex->line_start, *ex->line_term, *enclosed,
328
314
info.escape_char, is_fifo);
329
315
if (read_info.error)
390
376
internal::my_close(file,MYF(0));
391
377
free_blobs(table); /* if pack_blob was used */
392
378
table->copy_blobs=0;
393
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
379
session->count_cuted_fields= CHECK_FIELD_IGNORE;
395
381
simulated killing in the middle of per-row loop
396
382
must be effective for binlogging
398
killed_status= (error == 0)? Session::NOT_KILLED : session->getKilled();
384
killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
401
387
error= -1; // Error on read
406
snprintf(msg, sizeof(msg), ER(ER_LOAD_INFO), info.records, info.deleted,
407
(info.records - info.copied), session->cuted_fields);
409
if (session->transaction.stmt.hasModifiedNonTransData())
410
session->transaction.all.markModifiedNonTransData();
390
sprintf(name, ER(ER_LOAD_INFO), (uint32_t) info.records, (uint32_t) info.deleted,
391
(uint32_t) (info.records - info.copied), (uint32_t) session->cuted_fields);
393
if (session->transaction.stmt.modified_non_trans_table)
394
session->transaction.all.modified_non_trans_table= true;
412
396
/* ok to client sent only after binlog write and engine commit */
413
session->my_ok(info.copied + info.deleted, 0, 0L, msg);
397
session->my_ok(info.copied + info.deleted, 0, 0L, name);
415
399
assert(transactional_table || !(info.copied || info.deleted) ||
416
session->transaction.stmt.hasModifiedNonTransData());
400
session->transaction.stmt.modified_non_trans_table);
417
401
table->cursor->ha_release_auto_increment();
418
402
table->auto_increment_field_not_null= false;
419
session->setAbortOnWarning(false);
403
session->abort_on_warning= 0;