Пример #1
0
int
SQLautocommit(Client c, mvc *m)
{
	if (m->session->auto_commit && m->session->active) {
		if (mvc_status(m) < 0) {
			RECYCLEdrop(0);
			mvc_rollback(m, 0, NULL);
		} else if (mvc_commit(m, 0, NULL) < 0) {
			return handle_error(m, c->fdout, 0);
		}
	}
	return TRUE;
}
Пример #2
0
str
SQLexitClient(Client c)
{
#ifdef _SQL_SCENARIO_DEBUG
	mnstr_printf(GDKout, "#SQLexitClient\n");
#endif
	if (SQLinitialized == FALSE)
		throw(SQL, "SQLexitClient", "Catalogue not available");
	if (c->sqlcontext) {
		backend *be = NULL;
		mvc *m = NULL;
		if (c->sqlcontext == NULL)
			throw(SQL, "SQLexitClient", "MVC catalogue not available");
		be = (backend *) c->sqlcontext;
		m = be->mvc;

		assert(m->session);
		if (m->session->auto_commit && m->session->active) {
			if (mvc_status(m) >= 0 && mvc_commit(m, 0, NULL) < 0)
				(void) handle_error(m, c->fdout, 0);
		}
		if (m->session->active) {
			RECYCLEdrop(0);
			mvc_rollback(m, 0, NULL);
		}

		res_tables_destroy(m->results);
		m->results = NULL;

		mvc_destroy(m);
		backend_destroy(be);
		c->state[MAL_SCENARIO_OPTIMIZE] = NULL;
		c->state[MAL_SCENARIO_PARSER] = NULL;
		c->sqlcontext = NULL;
	}
	c->state[MAL_SCENARIO_READER] = NULL;
	return MAL_SUCCEED;
}
Пример #3
0
int
mvc_init(int debug, store_type store, int ro, int su, backend_stack stk)
{
	int first = 0;

	logger_settings *log_settings = (struct logger_settings *) GDKmalloc(sizeof(struct logger_settings));
	/* Set the default WAL directory. "sql_logs" by default */
	log_settings->logdir = "sql_logs";
	/* Get and pass on the WAL directory location, if set */
	if (GDKgetenv("gdk_logdir") != NULL) {
		log_settings->logdir = GDKgetenv("gdk_logdir");
	}
	/* Get and pass on the shared WAL directory location, if set */
	log_settings->shared_logdir = GDKgetenv("gdk_shared_logdir");
	/* Get and pass on the shared WAL drift threshold, if set.
	 * -1 by default, meaning it should be ignored, since it is not set */
	log_settings->shared_drift_threshold = GDKgetenv_int("gdk_shared_drift_threshold", -1);

	/* Get and pass on the flag how many WAL files should be preserved.
	 * 0 by default - keeps only the current WAL file. */
	log_settings->keep_persisted_log_files = GDKgetenv_int("gdk_keep_persisted_log_files", 0);

	mvc_debug = debug&4;
	if (mvc_debug) {
		fprintf(stderr, "#mvc_init logdir %s\n", log_settings->logdir);
		fprintf(stderr, "#mvc_init keep_persisted_log_files %d\n", log_settings->keep_persisted_log_files);
		if (log_settings->shared_logdir != NULL) {
			fprintf(stderr, "#mvc_init shared_logdir %s\n", log_settings->shared_logdir);
		}
		fprintf(stderr, "#mvc_init shared_drift_threshold %d\n", log_settings->shared_drift_threshold);
	}
	keyword_init();
	scanner_init_keywords();


	if ((first = store_init(debug, store, ro, su, log_settings, stk)) < 0) {
		fprintf(stderr, "!mvc_init: unable to create system tables\n");
		return -1;
	}
	if (first || catalog_version) {
		sql_schema *s;
		sql_table *t;
		mvc *m = mvc_create(0, stk, 0, NULL, NULL);

		m->sa = sa_create();

		/* disable caching */
		m->caching = 0;
		/* disable history */
		m->history = 0;
		/* disable size header */
		m->sizeheader = 0;
		mvc_trans(m);
		s = m->session->schema = mvc_bind_schema(m, "sys");
		assert(m->session->schema != NULL);

		if (!first) {
			t = mvc_bind_table(m, s, "tables");
			mvc_drop_table(m, s, t, 0);
			t = mvc_bind_table(m, s, "columns");
			mvc_drop_table(m, s, t, 0);
		}

		t = mvc_create_view(m, s, "tables", SQL_PERSIST, "SELECT \"id\", \"name\", \"schema_id\", \"query\", CAST(CASE WHEN \"system\" THEN \"type\" + 10 /* system table/view */ ELSE (CASE WHEN \"commit_action\" = 0 THEN \"type\" /* table/view */ ELSE \"type\" + 20 /* global temp table */ END) END AS SMALLINT) AS \"type\", \"system\", \"commit_action\", \"access\", CASE WHEN (NOT \"system\" AND \"commit_action\" > 0) THEN 1 ELSE 0 END AS \"temporary\" FROM \"sys\".\"_tables\" WHERE \"type\" <> 2 UNION ALL SELECT \"id\", \"name\", \"schema_id\", \"query\", CAST(\"type\" + 30 /* local temp table */ AS SMALLINT) AS \"type\", \"system\", \"commit_action\", \"access\", 1 AS \"temporary\" FROM \"tmp\".\"_tables\";", 1);
		mvc_create_column_(m, t, "id", "int", 32);
		mvc_create_column_(m, t, "name", "varchar", 1024);
		mvc_create_column_(m, t, "schema_id", "int", 32);
		mvc_create_column_(m, t, "query", "varchar", 2048);
		mvc_create_column_(m, t, "type", "smallint", 16);
		mvc_create_column_(m, t, "system", "boolean", 1);
		mvc_create_column_(m, t, "commit_action", "smallint", 16);
		mvc_create_column_(m, t, "access", "smallint", 16);
		mvc_create_column_(m, t, "temporary", "smallint", 16);

		if (!first) {
			int pub = ROLE_PUBLIC;
			int p = PRIV_SELECT;
			int zero = 0;
			sql_table *privs = find_sql_table(s, "privileges");
			table_funcs.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
		}

		t = mvc_create_view(m, s, "columns", SQL_PERSIST, "SELECT * FROM (SELECT p.* FROM \"sys\".\"_columns\" AS p UNION ALL SELECT t.* FROM \"tmp\".\"_columns\" AS t) AS columns;", 1);
		mvc_create_column_(m, t, "id", "int", 32);
		mvc_create_column_(m, t, "name", "varchar", 1024);
		mvc_create_column_(m, t, "type", "varchar", 1024);
		mvc_create_column_(m, t, "type_digits", "int", 32);
		mvc_create_column_(m, t, "type_scale", "int", 32);
		mvc_create_column_(m, t, "table_id", "int", 32);
		mvc_create_column_(m, t, "default", "varchar", 2048);
		mvc_create_column_(m, t, "null", "boolean", 1);
		mvc_create_column_(m, t, "number", "int", 32);
		mvc_create_column_(m, t, "storage", "varchar", 2048);

		if (!first) {
			int pub = ROLE_PUBLIC;
			int p = PRIV_SELECT;
			int zero = 0;
			sql_table *privs = find_sql_table(s, "privileges");
			table_funcs.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
		} else { 
			sql_create_env(m, s);
			sql_create_privileges(m, s);
		}

		s = m->session->schema = mvc_bind_schema(m, "tmp");
		assert(m->session->schema != NULL);

		if (mvc_commit(m, 0, NULL) < 0) {
			fprintf(stderr, "!mvc_init: unable to commit system tables\n");
			return -1;
		}

		mvc_destroy(m);
	}
	return first;
}
Пример #4
0
str
SQLparser(Client c)
{
	bstream *in = c->fdin;
	stream *out = c->fdout;
	str msg = NULL;
	backend *be;
	mvc *m;
	int oldvtop, oldstop;
	int pstatus = 0;
	int err = 0, opt = 0;

	be = (backend *) c->sqlcontext;
	if (be == 0) {
		/* tell the client */
		mnstr_printf(out, "!SQL state descriptor missing, aborting\n");
		mnstr_flush(out);
		/* leave a message in the log */
		fprintf(stderr, "SQL state descriptor missing, cannot handle client!\n");
		/* stop here, instead of printing the exception below to the
		 * client in an endless loop */
		c->mode = FINISHCLIENT;
		throw(SQL, "SQLparser", "State descriptor missing");
	}
	oldvtop = c->curprg->def->vtop;
	oldstop = c->curprg->def->stop;
	be->vtop = oldvtop;
#ifdef _SQL_PARSER_DEBUG
	mnstr_printf(GDKout, "#SQL compilation \n");
	printf("debugger? %d(%d)\n", (int) be->mvc->emode, (int) be->mvc->emod);
#endif
	m = be->mvc;
	m->type = Q_PARSE;
	SQLtrans(m);
	pstatus = m->session->status;

	/* sqlparse needs sql allocator to be available.  It can be NULL at
	 * this point if this is a recursive call. */
	if (!m->sa)
		m->sa = sa_create();

	m->emode = m_normal;
	m->emod = mod_none;
	if (be->language == 'X') {
		int n = 0, v, off, len;

		if (strncmp(in->buf + in->pos, "export ", 7) == 0)
			n = sscanf(in->buf + in->pos + 7, "%d %d %d", &v, &off, &len);

		if (n == 2 || n == 3) {
			mvc_export_chunk(be, out, v, off, n == 3 ? len : m->reply_size);

			in->pos = in->len;	/* HACK: should use parsed length */
			return MAL_SUCCEED;
		}
		if (strncmp(in->buf + in->pos, "close ", 6) == 0) {
			res_table *t;

			v = (int) strtol(in->buf + in->pos + 6, NULL, 0);
			t = res_tables_find(m->results, v);
			if (t)
				m->results = res_tables_remove(m->results, t);
			in->pos = in->len;	/* HACK: should use parsed length */
			return MAL_SUCCEED;
		}
		if (strncmp(in->buf + in->pos, "release ", 8) == 0) {
			cq *q = NULL;

			v = (int) strtol(in->buf + in->pos + 8, NULL, 0);
			if ((q = qc_find(m->qc, v)) != NULL)
				 qc_delete(m->qc, q);
			in->pos = in->len;	/* HACK: should use parsed length */
			return MAL_SUCCEED;
		}
		if (strncmp(in->buf + in->pos, "auto_commit ", 12) == 0) {
			int commit;
			v = (int) strtol(in->buf + in->pos + 12, NULL, 10);
			commit = (!m->session->auto_commit && v);
			m->session->auto_commit = (v) != 0;
			m->session->ac_on_commit = m->session->auto_commit;
			if (m->session->active) {
				if (commit && mvc_commit(m, 0, NULL) < 0) {
					mnstr_printf(out, "!COMMIT: commit failed while " "enabling auto_commit\n");
					msg = createException(SQL, "SQLparser", "Xauto_commit (commit) failed");
				} else if (!commit && mvc_rollback(m, 0, NULL) < 0) {
					RECYCLEdrop(0);
					mnstr_printf(out, "!COMMIT: rollback failed while " "disabling auto_commit\n");
					msg = createException(SQL, "SQLparser", "Xauto_commit (rollback) failed");
				}
			}
			in->pos = in->len;	/* HACK: should use parsed length */
			if (msg != NULL)
				goto finalize;
			return MAL_SUCCEED;
		}
		if (strncmp(in->buf + in->pos, "reply_size ", 11) == 0) {
			v = (int) strtol(in->buf + in->pos + 11, NULL, 10);
			if (v < -1) {
				msg = createException(SQL, "SQLparser", "reply_size cannot be negative");
				goto finalize;
			}
			m->reply_size = v;
			in->pos = in->len;	/* HACK: should use parsed length */
			return MAL_SUCCEED;
		}
		if (strncmp(in->buf + in->pos, "sizeheader", 10) == 0) {
			v = (int) strtol(in->buf + in->pos + 10, NULL, 10);
			m->sizeheader = v != 0;
			in->pos = in->len;	/* HACK: should use parsed length */
			return MAL_SUCCEED;
		}
		if (strncmp(in->buf + in->pos, "quit", 4) == 0) {
			c->mode = FINISHCLIENT;
			return MAL_SUCCEED;
		}
		mnstr_printf(out, "!unrecognized X command: %s\n", in->buf + in->pos);
		msg = createException(SQL, "SQLparser", "unrecognized X command");
		goto finalize;
	}
	if (be->language !='S') {
		mnstr_printf(out, "!unrecognized language prefix: %ci\n", be->language);
		msg = createException(SQL, "SQLparser", "unrecognized language prefix: %c", be->language);
		goto finalize;
	}

	if ((err = sqlparse(m)) ||
	    /* Only forget old errors on transaction boundaries */
	    (mvc_status(m) && m->type != Q_TRANS) || !m->sym) {
		if (!err &&m->scanner.started)	/* repeat old errors, with a parsed query */
			err = mvc_status(m);
		if (err) {
			msg = createException(PARSE, "SQLparser", "%s", m->errstr);
			handle_error(m, c->fdout, pstatus);
		}
		sqlcleanup(m, err);
		goto finalize;
	}
	assert(m->session->schema != NULL);
	/*
	 * We have dealt with the first parsing step and advanced the input reader
	 * to the next statement (if any).
	 * Now is the time to also perform the semantic analysis, optimize and
	 * produce code.
	 */
	be->q = NULL;
	if (m->emode == m_execute) {
		assert(m->sym->data.lval->h->type == type_int);
		be->q = qc_find(m->qc, m->sym->data.lval->h->data.i_val);
		if (!be->q) {
			err = -1;
			mnstr_printf(out, "!07003!EXEC: no prepared statement with id: %d\n", m->sym->data.lval->h->data.i_val);
			msg = createException(SQL, "PREPARE", "no prepared statement with id: %d", m->sym->data.lval->h->data.i_val);
			handle_error(m, c->fdout, pstatus);
			sqlcleanup(m, err);
			goto finalize;
		} else if (be->q->type != Q_PREPARE) {
			err = -1;
			mnstr_printf(out, "!07005!EXEC: given handle id is not for a " "prepared statement: %d\n", m->sym->data.lval->h->data.i_val);
			msg = createException(SQL, "PREPARE", "is not a prepared statement: %d", m->sym->data.lval->h->data.i_val);
			handle_error(m, c->fdout, pstatus);
			sqlcleanup(m, err);
			goto finalize;
		}
		m->emode = m_inplace;
		scanner_query_processed(&(m->scanner));
	} else if (caching(m) && cachable(m, NULL) && m->emode != m_prepare && (be->q = qc_match(m->qc, m->sym, m->args, m->argc, m->scanner.key ^ m->session->schema->base.id)) != NULL) {
		// look for outdated plans
		if ( OPTmitosisPlanOverdue(c, be->q->name) ){
			msg = SQLCacheRemove(c, be->q->name);
			qc_delete(be->mvc->qc, be->q);
			goto recompilequery;
		}

		if (m->emod & mod_debug)
			SQLsetDebugger(c, m, TRUE);
		if (m->emod & mod_trace)
			SQLsetTrace(be, c, TRUE);
		if (!(m->emod & (mod_explain | mod_debug | mod_trace | mod_dot)))
			m->emode = m_inplace;
		scanner_query_processed(&(m->scanner));
	} else {
		sql_rel *r;
		stmt *s;
recompilequery:
		r = sql_symbol2relation(m, m->sym);
		s = sql_relation2stmt(m, r);

		if (s == 0 || (err = mvc_status(m) && m->type != Q_TRANS)) {
			msg = createException(PARSE, "SQLparser", "%s", m->errstr);
			handle_error(m, c->fdout, pstatus);
			sqlcleanup(m, err);
			goto finalize;
		}
		assert(s);

		/* generate the MAL code */
		if (m->emod & mod_trace)
			SQLsetTrace(be, c, TRUE);
		if (m->emod & mod_debug)
			SQLsetDebugger(c, m, TRUE);
		if (!caching(m) || !cachable(m, s)) {
			scanner_query_processed(&(m->scanner));
			if (backend_callinline(be, c, s, 0) == 0) {
				opt = 1;
			} else {
				err = 1;
			}
		} else {
			/* generate a factory instantiation */
			be->q = qc_insert(m->qc, m->sa,	/* the allocator */
					  r,	/* keep relational query */
					  m->sym,	/* the sql symbol tree */
					  m->args,	/* the argument list */
					  m->argc, m->scanner.key ^ m->session->schema->base.id,	/* the statement hash key */
					  m->emode == m_prepare ? Q_PREPARE : m->type,	/* the type of the statement */
					  sql_escape_str(QUERY(m->scanner)));
			scanner_query_processed(&(m->scanner));
			be->q->code = (backend_code) backend_dumpproc(be, c, be->q, s);
			if (!be->q->code)
				err = 1;
			be->q->stk = 0;

			/* passed over to query cache, used during dumpproc */
			m->sa = NULL;
			m->sym = NULL;

			/* register name in the namespace */
			be->q->name = putName(be->q->name, strlen(be->q->name));
			if (m->emode == m_normal && m->emod == mod_none)
				m->emode = m_inplace;
		}
	}
	if (err)
		m->session->status = -10;
	if (err == 0) {
		if (be->q) {
			if (m->emode == m_prepare)
				err = mvc_export_prepare(m, c->fdout, be->q, "");
			else if (m->emode == m_inplace) {
				/* everything ready for a fast call */
			} else {	/* call procedure generation (only in cache mode) */
				backend_call(be, c, be->q);
			}
		}

		/* In the final phase we add any debugging control */
		if (m->emod & mod_trace)
			SQLsetTrace(be, c, FALSE);
		if (m->emod & mod_debug)
			SQLsetDebugger(c, m, FALSE);

		/*
		 * During the execution of the query exceptions can be raised.
		 * The default action is to print them out at the end of the
		 * query block.
		 */
		pushEndInstruction(c->curprg->def);

		chkTypes(c->fdout, c->nspace, c->curprg->def, TRUE);	/* resolve types */
		if (opt) {
			MalBlkPtr mb = c->curprg->def;

			trimMalBlk(mb);
			chkProgram(c->fdout, c->nspace, mb);
			addOptimizers(c, mb, "default_pipe");
			msg = optimizeMALBlock(c, mb);
			if (msg != MAL_SUCCEED) {
				sqlcleanup(m, err);
				goto finalize;
			}
			c->curprg->def = mb;
		}
		//printFunction(c->fdout, c->curprg->def, 0, LIST_MAL_ALL);
		/* we know more in this case than chkProgram(c->fdout, c->nspace, c->curprg->def); */
		if (c->curprg->def->errors) {
			showErrors(c);
			/* restore the state */
			MSresetInstructions(c->curprg->def, oldstop);
			freeVariables(c, c->curprg->def, c->glb, oldvtop);
			c->curprg->def->errors = 0;
			msg = createException(PARSE, "SQLparser", "Semantic errors");
		}
	}
      finalize:
	if (msg)
		sqlcleanup(m, 0);
	return msg;
}
Пример #5
0
int
mvc_init(int debug, store_type store, backend_stack stk)
{
	int first = 0;
	char *logdir = "sql_logs";

	mvc_debug = debug;
	if (mvc_debug)
		fprintf(stderr, "#mvc_init logdir %s\n", logdir);
	keyword_init();
	scanner_init_keywords();

	if ((first = store_init(debug, store, logdir, stk)) < 0) {
		fprintf(stderr, "!mvc_init: unable to create system tables\n");
		return -1;
	}
	if (first || catalog_version) {
		sql_schema *s;
		sql_table *t;
		mvc *m = mvc_create(0, stk, 0, NULL, NULL);

		/* disable caching */
		m->caching = 0;
		/* disable history */
		m->history = 0;
		/* disable size header */
		m->sizeheader = 0;
		mvc_trans(m);
		s = m->session->schema = mvc_bind_schema(m, "sys");
		assert(m->session->schema != NULL);

		if (catalog_version) {
			t = mvc_bind_table(m, s, "tables");
			mvc_drop_table(m, s, t, 0);
			t = mvc_bind_table(m, s, "columns");
			mvc_drop_table(m, s, t, 0);
		}

		t = mvc_create_view(m, s, "tables", SQL_PERSIST, "SELECT * FROM (SELECT p.*, 0 AS \"temporary\" FROM \"sys\".\"_tables\" AS p UNION ALL SELECT t.*, 1 AS \"temporary\" FROM \"tmp\".\"_tables\" AS t) AS tables where tables.type <> 2;", 1);
		mvc_create_column_(m, t, "id", "int", 32);
		mvc_create_column_(m, t, "name", "varchar", 1024);
		mvc_create_column_(m, t, "schema_id", "int", 32);
		mvc_create_column_(m, t, "query", "varchar", 2048);
		mvc_create_column_(m, t, "type", "smallint", 16);
		mvc_create_column_(m, t, "system", "boolean", 1);
		mvc_create_column_(m, t, "commit_action", "smallint", 16);
		mvc_create_column_(m, t, "readonly", "boolean", 1);
		mvc_create_column_(m, t, "temporary", "smallint", 16);

		if (catalog_version) {
			int pub = ROLE_PUBLIC;
			int p = PRIV_SELECT;
			int zero = 0;
			sql_table *privs = find_sql_table(s, "privileges");
			table_funcs.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
		}

		t = mvc_create_view(m, s, "columns", SQL_PERSIST, "SELECT * FROM (SELECT p.* FROM \"sys\".\"_columns\" AS p UNION ALL SELECT t.* FROM \"tmp\".\"_columns\" AS t) AS columns;", 1);
		mvc_create_column_(m, t, "id", "int", 32);
		mvc_create_column_(m, t, "name", "varchar", 1024);
		mvc_create_column_(m, t, "type", "varchar", 1024);
		mvc_create_column_(m, t, "type_digits", "int", 32);
		mvc_create_column_(m, t, "type_scale", "int", 32);
		mvc_create_column_(m, t, "table_id", "int", 32);
		mvc_create_column_(m, t, "default", "varchar", 2048);
		mvc_create_column_(m, t, "null", "boolean", 1);
		mvc_create_column_(m, t, "number", "int", 32);
		/* TODO: the code below is out-of-date.  Should be changed into the
		 * following with the next major catalogue change:
		 * mvc_create_column(m, t, "storage", "varchar", 2048);
		 */
		mvc_create_column_(m, t, "storage_type", "int", 32);

		if (catalog_version) {
			int pub = ROLE_PUBLIC;
			int p = PRIV_SELECT;
			int zero = 0;
			sql_table *privs = find_sql_table(s, "privileges");
			table_funcs.table_insert(m->session->tr, privs, &t->base.id, &pub, &p, &zero, &zero);
		}

		if (!catalog_version) {
			sql_create_env(m, s);
			sql_create_privileges(m, s);
		}

		s = m->session->schema = mvc_bind_schema(m, "tmp");
		assert(m->session->schema != NULL);

		if (mvc_commit(m, 0, NULL) < 0) {
			fprintf(stderr, "!mvc_init: unable to commit system tables\n");
			return -1;
		}

		mvc_destroy(m);
	}
	return first;
}