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>
121
119
true - error / false - success
124
int load(Session *session,file_exchange *ex,TableList *table_list,
122
int mysql_load(Session *session,file_exchange *ex,TableList *table_list,
125
123
List<Item> &fields_vars, List<Item> &set_fields,
126
124
List<Item> &set_values,
127
125
enum enum_duplicates handle_duplicates, bool ignore)
127
char name[FN_REFLEN];
130
129
Table *table= NULL;
132
131
String *field_term=ex->field_term,*escaped=ex->escaped;
133
132
String *enclosed=ex->enclosed;
136
assert(table_list->getSchemaName()); // This should never be null
134
char *db= table_list->db; // This is never null
139
137
If path for cursor is not defined, we will use the current database.
140
138
If this is not set, we will use the directory where the table to be
141
139
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
141
const char *tdb= session->db.empty() ? db : session->db.c_str(); // Result is never null
146
143
uint32_t skip_lines= ex->skip_lines;
147
144
bool transactional_table;
148
Session::killed_state_t killed_status= Session::NOT_KILLED;
145
Session::killed_state killed_status= Session::NOT_KILLED;
150
147
/* Escape and enclosed character may be a utf8 4-byte character */
151
148
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");
258
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
259
ex->file_name+=dirname_length(ex->file_name);
261
if (!internal::dirname_length(ex->file_name))
263
strcpy(name, getDataHomeCatalog().c_str());
264
strncat(name, "/", 1);
265
strncat(name, tdb, FN_REFLEN-getDataHomeCatalog().size());
266
(void) internal::fn_format(name, ex->file_name, name, "",
267
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
271
(void) internal::fn_format(name, ex->file_name, getDataHomeCatalog().c_str(), "",
272
MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
274
if (opt_secure_file_priv)
276
fs::path secure_file_path(fs::system_complete(fs::path(opt_secure_file_priv)));
277
fs::path target_path(fs::system_complete(fs::path(name)));
278
if (target_path.file_string().substr(0, secure_file_path.file_string().size()) != secure_file_path.file_string())
280
/* Read only allowed from within dir specified by secure_file_priv */
281
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
286
struct stat stat_info;
287
if (stat(name,&stat_info))
289
my_error(ER_FILE_NOT_FOUND, MYF(0), name, errno);
293
// if we are not in slave thread, the cursor must be:
294
if (!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
295
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
296
((stat_info.st_mode & S_IFREG) == S_IFREG ||
297
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
299
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
302
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
305
if ((file=internal::my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
307
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
313
memset(&info, 0, sizeof(info));
320
314
info.ignore= ignore;
321
315
info.handle_duplicates=handle_duplicates;
322
316
info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX;
324
identifier::Schema identifier(*schema);
318
SchemaIdentifier identifier(session->db);
325
319
READ_INFO read_info(file, tot_length,
326
320
ex->cs ? ex->cs : plugin::StorageEngine::getSchemaCollation(identifier),
327
321
*field_term, *ex->line_start, *ex->line_term, *enclosed,
395
389
simulated killing in the middle of per-row loop
396
390
must be effective for binlogging
398
killed_status= (error == 0)? Session::NOT_KILLED : session->getKilled();
392
killed_status= (error == 0)? Session::NOT_KILLED : session->killed;
401
395
error= -1; // Error on read
406
snprintf(msg, sizeof(msg), ER(ER_LOAD_INFO), info.records, info.deleted,
398
snprintf(name, sizeof(name), ER(ER_LOAD_INFO), info.records, info.deleted,
407
399
(info.records - info.copied), session->cuted_fields);
409
401
if (session->transaction.stmt.hasModifiedNonTransData())
410
402
session->transaction.all.markModifiedNonTransData();
412
404
/* ok to client sent only after binlog write and engine commit */
413
session->my_ok(info.copied + info.deleted, 0, 0L, msg);
405
session->my_ok(info.copied + info.deleted, 0, 0L, name);
415
407
assert(transactional_table || !(info.copied || info.deleted) ||
416
408
session->transaction.stmt.hasModifiedNonTransData());
417
409
table->cursor->ha_release_auto_increment();
418
410
table->auto_increment_field_not_null= false;
419
session->setAbortOnWarning(false);
411
session->abort_on_warning= 0;
607
597
field->set_null();
608
if (not field->maybe_null())
598
if (!field->maybe_null())
610
if (field->is_timestamp())
612
((field::Epoch::pointer) field)->set_time();
600
if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
601
((Field_timestamp*) field)->set_time();
614
602
else if (field != table->next_number_field)
616
field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_NULL_TO_NOTNULL, 1);
603
field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
604
ER_WARN_NULL_TO_NOTNULL, 1);
620
607
else if (item->type() == Item::STRING_ITEM)
807
794
end_of_buff=buffer+buff_length;
808
if (cache.init_io_cache((false) ? -1 : cursor, 0,
809
(false) ? internal::READ_NET :
810
(is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
795
if (init_io_cache(&cache,(false) ? -1 : cursor, 0,
796
(false) ? internal::READ_NET :
797
(is_fifo ? internal::READ_FIFO : internal::READ_CACHE),0L,1,
813
800
free((unsigned char*) buffer);