Exemplo n.º 1
0
int
mvc_rollback(mvc *m, int chain, const char *name)
{
	int res = 0;
	sql_trans *tr = m->session->tr;

	if (mvc_debug)
		fprintf(stderr, "#mvc_rollback %s\n", (name) ? name : "");

	assert(tr);
	assert(m->session->active);	/* only abort an active transaction */

	store_lock();
	if (m->qc) 
		qc_clean(m->qc);
	if (name && name[0] != '\0') {
		while (tr && (!tr->name || strcmp(tr->name, name) != 0))
			tr = tr->parent;
		if (!tr) {
			(void)sql_error(m, 010, "ROLLBACK: no such savepoint: '%s'", name);
			m->session->status = -1;
			store_unlock();
			return -1;
		}
		tr = m->session->tr;
		while (!tr->name || strcmp(tr->name, name) != 0) {
			/* make sure we do not reuse changed data */
			if (tr->wtime)
				tr->status = 1;
			tr = sql_trans_destroy(tr);
		}
		m->session->tr = tr;	/* restart at savepoint */
		m->session->status = tr->status;
		if (tr->name) 
			tr->name = NULL;
		m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name);
	} else if (tr->parent) {
		/* first release all intermediate savepoints */
		while (tr->parent->parent != NULL) {
			tr = sql_trans_destroy(tr);
		}
		m->session-> tr = tr;
		/* make sure we do not reuse changed data */
		if (tr->wtime)
			tr->status = 1;
		sql_trans_end(m->session);
		if (chain) 
			sql_trans_begin(m->session);
	}
	store_unlock();
	m->type = Q_TRANS;
	if (mvc_debug)
		fprintf(stderr, "#mvc_rollback %s done\n", (name) ? name : "");
	return res;
}
Exemplo n.º 2
0
int
seq_next_value(sql_sequence *seq, lng *val)
{
	lng nr = 0;
	node *n = NULL;
	store_sequence *s;
	int save = 0;

	*val = 0;
	store_lock();
	for ( n = sql_seqs->h; n; n = n ->next ) {
		s = n->data;
		if (s->seqid == seq->base.id)
			break;
	}
	if (!n) {
		s = sql_create_sequence(seq);
		if (!s) {
			store_unlock();
			return 0;
		}
		list_append(sql_seqs, s);
	} else {
		s = n->data;
		if (s->called)
			s->cur += seq->increment;
	}
	/* handle min/max and cycle */
	if ((seq->maxvalue && s->cur > seq->maxvalue) ||
	    (seq->minvalue && s->cur < seq->minvalue))
	{
		if (seq->cycle) {
			/* cycle to the min value again */
			s->cur = seq->minvalue;
			save = 1;
		} else { /* we're out of numbers */
			store_unlock();
			return 0;
		}
	}
	s->called = 1;
	nr = s->cur;
	*val = nr;
	if (save || nr == s->cached) {
		s->cached = nr + seq->cacheinc*seq->increment;
		sql_update_sequence_cache(seq, s->cached);
		store_unlock(); 
		return 1;
	}
	assert(nr<s->cached);
	store_unlock(); 
	return 1;
}
Exemplo n.º 3
0
seqbulk *seqbulk_create(sql_sequence *seq, BUN cnt)
{
	seqbulk *sb = MNEW(seqbulk);
	store_sequence *s;
	node *n = NULL;

	if (!sb)
		return NULL;

	store_lock();
	sb->seq = seq;
	sb->cnt = cnt;
	sb->save = 0;

	for ( n = sql_seqs->h; n; n = n ->next ) {
		s = n->data;
		if (s->seqid == seq->base.id)
			break;
	}
	if (!n) {
		s = sql_create_sequence(seq);
		if (!s) {
			_DELETE(sb);
			store_unlock();
			return NULL;
		}
		list_append(sql_seqs, s);
	} else {
		s = n->data;
	}
	sb->internal_seq = s;
	return sb;
}
Exemplo n.º 4
0
mvc *
mvc_create(int clientid, backend_stack stk, int debug, bstream *rs, stream *ws)
{
	int i;
	mvc *m;

 	m = ZNEW(mvc);
	if (mvc_debug)
		fprintf(stderr, "#mvc_create\n");

	m->errstr[0] = '\0';
	/* if an error exceeds the buffer we don't want garbage at the end */
	m->errstr[ERRSIZE-1] = '\0';

	m->qc = qc_create(clientid, 0);
	m->sa = NULL;

	m->params = NULL;
	m->sizevars = MAXPARAMS;
	m->vars = NEW_ARRAY(sql_var, m->sizevars);
	m->topvars = 0;
	m->frame = 1;
	m->use_views = 0;
	m->argmax = MAXPARAMS;
	m->args = NEW_ARRAY(atom*,m->argmax);
	m->argc = 0;
	m->sym = NULL;

	m->rowcnt = m->last_id = m->role_id = m->user_id = -1;
	m->timezone = 0;
	m->clientid = clientid;

	m->emode = m_normal;
	m->emod = mod_none;
	m->reply_size = 100;
	m->debug = debug;
	m->cache = DEFAULT_CACHESIZE;
	m->caching = m->cache;
	m->history = 0;

	m->label = 0;
	m->cascade_action = NULL;
	for(i=0;i<MAXSTATS;i++)
		m->opt_stats[i] = 0;

	store_lock();
	m->session = sql_session_create(stk, 1 /*autocommit on*/);
	store_unlock();

	m->type = Q_PARSE;
	m->pushdown = 1;

	m->result_id = 0;
	m->results = NULL;

	scanner_init(&m->scanner, rs, ws);
	return m;
}
Exemplo n.º 5
0
void seqbulk_destroy(seqbulk *sb)
{
	if (sb->save) {
		sql_sequence *seq = sb->seq;
		store_sequence *s = sb->internal_seq;

		sql_update_sequence_cache(seq, s->cached);
	}
	_DELETE(sb);
	store_unlock();
}
Exemplo n.º 6
0
int
seq_get_value(sql_sequence *seq, lng *val)
{
	node *n = NULL;
	store_sequence *s;

	*val = 0;
	store_lock();
	for ( n = sql_seqs->h; n; n = n ->next ) {
		s = n->data;
		if (s->seqid == seq->base.id)
			break;
	}
	if (!n) {
		s = sql_create_sequence(seq);
		if (!s) {
			store_unlock();
			return 0;
		}
		list_append(sql_seqs, s);
	} else {
		s = n->data;
	}
	*val = s->cur;
	if (s->called)
		*val += seq->increment;
	/* handle min/max and cycle */
	if ((seq->maxvalue && *val > seq->maxvalue) ||
	    (seq->minvalue && *val < seq->minvalue))
	{
		if (seq->cycle) {
			/* cycle to the min value again */
			*val = seq->minvalue;
		} else { /* we're out of numbers */
			store_unlock();
			return 0;
		}
	}
	store_unlock();
	return 1;
}
Exemplo n.º 7
0
int seq_restart(sql_sequence *seq, lng start)
{
	node *n = NULL;
	store_sequence *s;

	store_lock();
	for ( n = sql_seqs->h; n; n = n ->next ) {
		s = n->data;
		if (s->seqid == seq->base.id)
			break;
	}
	if (!n) {
		s = sql_create_sequence(seq);
		if (!s) {
			store_unlock();
			return 0;
		}
		list_append(sql_seqs, s);
	} else {
		s = n->data;
	}
	s->called = 0;
	s->cur = start;
	s->cached = start;
	/* handle min/max and cycle */
	if ((seq->maxvalue && s->cur > seq->maxvalue) ||
	    (seq->minvalue && s->cur < seq->minvalue))
	{
		/* we're out of numbers */
		store_unlock();
		return 0;
	}
	sql_update_sequence_cache(seq, s->cached);
	store_unlock(); 
	return 1;
}
Exemplo n.º 8
0
void
mvc_trans(mvc *m)
{
	int schema_changed = 0, err = m->session->status;
	assert(!m->session->active);	/* can only start a new transaction */

	store_lock();
	schema_changed = sql_trans_begin(m->session);
	if (m->qc && (schema_changed || m->qc->nr > m->cache || err)){
		if (schema_changed || err) {
			int seqnr = m->qc->id;
			if (m->qc)
				qc_destroy(m->qc);
			m->qc = qc_create(m->clientid, seqnr);
		} else { /* clean all but the prepared statements */
			qc_clean(m->qc);
		}
	}
	store_unlock();
}
Exemplo n.º 9
0
/* release all savepoints up including the given named savepoint 
 * but keep the current changes.
 * */
int
mvc_release(mvc *m, const char *name)
{
	int ok = SQL_OK;
	int res = Q_TRANS;
	sql_trans *tr = m->session->tr;

	assert(tr);
	assert(m->session->active);	/* only release active transactions */

	if (mvc_debug)
		fprintf(stderr, "#mvc_release %s\n", (name) ? name : "");

	if (!name)
		mvc_rollback(m, 0, name);

	while (tr && (!tr->name || strcmp(tr->name, name) != 0))
		tr = tr->parent;
	if (!tr || !tr->name || strcmp(tr->name, name) != 0) {
		(void)sql_error(m, 010, "release savepoint %s doesn't exists", name);
		m->session->status = -1;
		return -1;
	}
	tr = m->session->tr;
	store_lock();
	while (ok == SQL_OK && (!tr->name || strcmp(tr->name, name) != 0)) {
		/* commit all intermediate savepoints */
		if (sql_trans_commit(tr) != SQL_OK)
			GDKfatal("release savepoints should not fail");
		tr = sql_trans_destroy(tr);
	}
	tr->name = NULL;
	store_unlock();
	m->session->tr = tr;
	m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name);

	m->type = res;
	return res;
}
Exemplo n.º 10
0
void
mvc_destroy(mvc *m)
{
	sql_trans *tr;

	if (mvc_debug)
		fprintf(stderr, "#mvc_destroy\n");
	tr = m->session->tr;
	if (tr) {
		store_lock();
		if (m->session->active)
			sql_trans_end(m->session);
		while (tr->parent)
			tr = sql_trans_destroy(tr);
		m->session->tr = NULL;
		store_unlock();
	}
	sql_session_destroy(m->session);

	stack_pop_until(m, 0);
	_DELETE(m->vars);

	if (m->scanner.log) /* close and destroy stream */
		close_stream(m->scanner.log);

	if (m->sa)
		sa_destroy(m->sa);
	m->sa = NULL;
	if (m->qc)
		qc_destroy(m->qc);
	m->qc = NULL;

	_DELETE(m->args);
	m->args = NULL;
	_DELETE(m);
}
Exemplo n.º 11
0
/* release all savepoints up including the given named savepoint 
 * but keep the current changes.
 * */
int
mvc_release(mvc *m, char *name)
{
	int ok = SQL_OK;
	int res = Q_TRANS;
	sql_trans *tr = m->session->tr;
	sql_trans *cur = tr;

	assert(tr);
	assert(m->session->active);	/* only release active transactions */

	if (mvc_debug)
		fprintf(stderr, "#mvc_release %s\n", (name) ? name : "");

	while (tr && (!tr->name || strcmp(tr->name, name) != 0))
		tr = tr->parent;
	if (!tr || !tr->name || strcmp(tr->name, name) != 0) {
		(void)sql_error(m, 010, "release savepoint %s doesn't exists", name);
		m->session->status = -1;
		return -1;
	}
	tr = m->session->tr;
	tr = tr->parent;
	store_lock();
	while (ok == SQL_OK && (!tr->name || strcmp(tr->name, name) != 0)) {
		tr = sql_trans_destroy(tr);
	}
	if (tr->name && strcmp(tr->name, name) == 0) {
		tr = sql_trans_destroy(tr);
	}
	store_unlock();
	cur -> parent = tr;

	m->type = res;
	return res;
}
Exemplo n.º 12
0
void
mvc_reset(mvc *m, bstream *rs, stream *ws, int debug, int globalvars)
{
	int i;
	sql_trans *tr;

	if (mvc_debug)
		fprintf(stderr, "#mvc_reset\n");
	tr = m->session->tr;
	if (tr && tr->parent) {
		assert(m->session->active == 0);
		store_lock();
		while (tr->parent->parent != NULL) 
			tr = sql_trans_destroy(tr);
		store_unlock();
	}
	if (tr)
		sql_session_reset(m->session, 1 /*autocommit on*/);

	if (m->sa)
		m->sa = sa_reset(m->sa);
	else 
		m->sa = sa_create();

	m->errstr[0] = '\0';

	m->params = NULL;
	/* reset topvars to the set of global variables */
	stack_pop_until(m, globalvars);
	m->frame = 1;
	m->argc = 0;
	m->sym = NULL;

	m->rowcnt = m->last_id = m->role_id = m->user_id = -1;
	m->emode = m_normal;
	m->emod = mod_none;
	if (m->reply_size != 100)
		stack_set_number(m, "reply_size", 100);
	m->reply_size = 100;
	if (m->timezone != 0)
		stack_set_number(m, "current_timezone", 0);
	m->timezone = 0;
	if (m->debug != debug)
		stack_set_number(m, "debug", debug);
	m->debug = debug;
	if (m->cache != DEFAULT_CACHESIZE)
		stack_set_number(m, "cache", DEFAULT_CACHESIZE);
	m->cache = DEFAULT_CACHESIZE;
	m->caching = m->cache;
	if (m->history != 0)
		stack_set_number(m, "history", 0);
	m->history = 0;

	m->label = 0;
	m->cascade_action = NULL;
	m->type = Q_PARSE;
	m->pushdown = 1;

	for(i=0;i<MAXSTATS;i++)
		m->opt_stats[i] = 0;

	m->result_id = 0;
	m->results = NULL;

	scanner_init(&m->scanner, rs, ws);
}
Exemplo n.º 13
0
int
mvc_commit(mvc *m, int chain, const char *name)
{
	sql_trans *cur, *tr = m->session->tr;
	int ok = SQL_OK;//, wait = 0;

	assert(tr);
	assert(m->session->active);	/* only commit an active transaction */
	
	if (mvc_debug)
		fprintf(stderr, "#mvc_commit %s\n", (name) ? name : "");

	if (m->session->status < 0) {
		(void)sql_error(m, 010, "40000!COMMIT: transaction is aborted, will ROLLBACK instead");
		mvc_rollback(m, chain, name);
		return -1;
	}

	/* savepoint then simply make a copy of the current transaction */
	if (name && name[0] != '\0') {
		sql_trans *tr = m->session->tr;
		if (mvc_debug)
			fprintf(stderr, "#mvc_savepoint\n");
		store_lock();
		m->session->tr = sql_trans_create(m->session->stk, tr, name);
		store_unlock();
		m->type = Q_TRANS;
		if (m->qc) /* clean query cache, protect against concurrent access on the hash tables (when functions already exists, concurrent mal will
build up the hash (not copied in the trans dup)) */
			qc_clean(m->qc);
		m->session->schema = find_sql_schema(m->session->tr, m->session->schema_name);
		if (mvc_debug)
			fprintf(stderr, "#mvc_commit %s done\n", name);
		return 0;
	}

	/* first release all intermediate savepoints */
	cur = tr;
	tr = tr->parent;
	if (tr->parent) {
		store_lock();
		while (tr->parent != NULL && ok == SQL_OK) {
			tr = sql_trans_destroy(tr);
		}
		store_unlock();
	}
	cur -> parent = tr;
	tr = cur;

	store_lock();
	/* if there is nothing to commit reuse the current transaction */
	if (tr->wtime == 0) {
		if (!chain) 
			sql_trans_end(m->session);
		m->type = Q_TRANS;
		if (mvc_debug)
			fprintf(stderr, "#mvc_commit %s done\n", (name) ? name : "");
		store_unlock();
		return 0;
	}

	/*
	while (tr->schema_updates && store_nr_active > 1) {
		store_unlock();
		MT_sleep_ms(100);
		wait += 100;
		if (wait > 1000) {
			(void)sql_error(m, 010, "40000!COMMIT: transaction is aborted because of DDL concurrency conflicts, will ROLLBACK instead");
			mvc_rollback(m, chain, name);
			return -1;
		}
		store_lock();
	}
	 * */
	/* validation phase */
	if (sql_trans_validate(tr)) {
		if ((ok = sql_trans_commit(tr)) != SQL_OK) {
			char *msg = sql_message("40000!COMMIT: transaction commit failed (perhaps your disk is full?) exiting (kernel error: %s)", GDKerrbuf);
			GDKfatal("%s", msg);
			_DELETE(msg);
		}
	} else {
		store_unlock();
		(void)sql_error(m, 010, "40000!COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead");
		mvc_rollback(m, chain, name);
		return -1;
	}
	sql_trans_end(m->session);
	if (chain) 
		sql_trans_begin(m->session);
	store_unlock();
	m->type = Q_TRANS;
	if (mvc_debug)
		fprintf(stderr, "#mvc_commit %s done\n", (name) ? name : "");
	return ok;
}