File db_method_static.cpp¶
File List > compat > db_method_static.cpp
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* db_method_static.cpp: implement static method links and their implementation
*/
#include "msgcat_glossary.hpp"
#include "dbi.h" /* db_ */
#include "dbtype.h"
#include "dbtype_def.h"
#include "authenticate.h" /* au_ */
#include "network_interface_cl.h" /* clogin_user */
#include "schema_manager.h" /* sm_issystem */
#include "execute_schema.h"
#include "execute_statement.h" /* do_get_serial_obj_id */
#include "transaction_cl.h" /* tran_system_savepoint */
#include "optimizer.h" /* qo_plan_set_cost_fn */
#include "object_print.h" /* help_print_info */
#include "jsp_cl.h" /* jsp_find_stored_procedure */
#include "transform.h" /* DB_MAX_SERIAL_NAME_LENGTH */
// ================================================================
// authenticate methods
// ================================================================
static void au_add_user_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *name, DB_VALUE *password);
static void au_drop_user_method (MOP root, DB_VALUE *returnval, DB_VALUE *name);
static void au_find_user_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *name);
static void au_add_member_method (MOP user, DB_VALUE *returnval, DB_VALUE *memval);
static void au_drop_member_method (MOP user, DB_VALUE *returnval, DB_VALUE *memval);
static void au_set_password_method (MOP user, DB_VALUE *returnval, DB_VALUE *password);
static void au_set_password_encoded_method (MOP user, DB_VALUE *returnval, DB_VALUE *password);
static void au_set_password_encoded_sha1_method (MOP user, DB_VALUE *returnval, DB_VALUE *password);
static void au_describe_user_method (MOP user, DB_VALUE *returnval);
static void au_describe_root_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *info);
static void au_info_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *info);
static void au_login_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *user, DB_VALUE *password);
static void au_change_owner_method (MOP obj, DB_VALUE *return_val, DB_VALUE *class_val, DB_VALUE *owner_val);
static void au_change_trigger_owner_method (MOP obj, DB_VALUE *return_val, DB_VALUE *trigger_val, DB_VALUE *owner_val);
static void au_get_owner_method (MOP obj, DB_VALUE *returnval, DB_VALUE *class_);
static void au_check_authorization_method (MOP obj, DB_VALUE *returnval, DB_VALUE *class_, DB_VALUE *auth);
static void au_change_serial_owner_method (MOP obj, DB_VALUE *return_val, DB_VALUE *serial_val, DB_VALUE *owner_val);
static void au_change_sp_owner_method (MOP obj, DB_VALUE *returnval, DB_VALUE *sp, DB_VALUE *owner);
/* 'get_attribute_number' is a statically linked method used only for QA
scenario */
static void get_attribute_number_method (DB_OBJECT *target, DB_VALUE *result, DB_VALUE *attr_name);
static void dbmeth_class_name (DB_OBJECT *self, DB_VALUE *result);
static void dbmeth_print (DB_OBJECT *self, DB_VALUE *result, DB_VALUE *msg);
// ================================================================
// optimizer methods
// ================================================================
/*
* qo_set_cost
*
* This function is exported by optimizer/query_planner.c, and provides a backdoor that
* allows us some gross manipulation capabilities for the query
* optimizer. By adding it to the list of method implementations that
* are statically linked we make it easy for us to add a method to an
* arbitrary class for those cases where we need to poke the optimizer.
* To use this, try
*
* alter class foo add method class set_cost(string, string)
* function qo_set_cost;
*
* and then utter
*
* call set_cost('iscan', '0') on class foo;
*/
static void qo_set_cost (DB_OBJECT *target, DB_VALUE *result, DB_VALUE *plan, DB_VALUE *cost);
// ================================================================
// dbmeth methods
// ================================================================
/*
* These functions are provided just so we have some builtin gadgets that we can
* use for quick and dirty method testing. To get at them, alter your
* favorite class like this:
*
* alter class foo
* add method pickaname() string
* function dbmeth_class_name;
*
* or
*
* alter class foo
* add method pickaname(string) string
* function dbmeth_print;
*
* After that you should be able to invoke "pickaname" on "foo" instances
* to your heart's content. dbmeth_class_name() will retrieve the class
* name of the target instance and return it as a string; dbmeth_print()
* will print the supplied value on stdout every time it is invoked.
*/
// ================================================================
// static link lists
// ================================================================
/*
* db_static_links
*
* Since authorization is always linked in with the database, the
* methods are defined statically. The linkage will be done
* during au_init even though it is redundant on subsequent
* restart calls.
*/
static DB_METHOD_LINK db_static_links[] =
{
{"au_add_user_method", (METHOD_LINK_FUNCTION) au_add_user_method},
{"au_drop_user_method", (METHOD_LINK_FUNCTION) au_drop_user_method},
{"au_find_user_method", (METHOD_LINK_FUNCTION) au_find_user_method},
{"au_add_member_method", (METHOD_LINK_FUNCTION) au_add_member_method},
{"au_drop_member_method", (METHOD_LINK_FUNCTION) au_drop_member_method},
{"au_set_password_method", (METHOD_LINK_FUNCTION) au_set_password_method},
{"au_set_password_encoded_method", (METHOD_LINK_FUNCTION) au_set_password_encoded_method},
{"au_set_password_encoded_sha1_method", (METHOD_LINK_FUNCTION) au_set_password_encoded_sha1_method},
{"au_describe_user_method", (METHOD_LINK_FUNCTION) au_describe_user_method},
{"au_describe_root_method", (METHOD_LINK_FUNCTION) au_describe_root_method},
{"au_info_method", (METHOD_LINK_FUNCTION) au_info_method},
{"au_login_method", (METHOD_LINK_FUNCTION) au_login_method},
{"au_change_owner_method", (METHOD_LINK_FUNCTION) au_change_owner_method},
{"au_change_trigger_owner_method", (METHOD_LINK_FUNCTION) au_change_trigger_owner_method},
{"au_get_owner_method", (METHOD_LINK_FUNCTION) au_get_owner_method},
{"au_check_authorization_method", (METHOD_LINK_FUNCTION) au_check_authorization_method},
{"qo_set_cost", (METHOD_LINK_FUNCTION) qo_set_cost},
{"get_attribute_number", (METHOD_LINK_FUNCTION) get_attribute_number_method},
{"dbmeth_class_name", (METHOD_LINK_FUNCTION) dbmeth_class_name},
{"dbmeth_print", (METHOD_LINK_FUNCTION) dbmeth_print},
{"au_change_sp_owner_method", (METHOD_LINK_FUNCTION) au_change_sp_owner_method},
{"au_change_serial_owner_method", (METHOD_LINK_FUNCTION) au_change_serial_owner_method},
{NULL, NULL}
};
/*
* db_install_static_methods() - Called during the restart sequence to statically
* link the methods defined in this file
* return: none
*/
void db_install_static_methods ()
{
db_link_static_methods (&db_static_links[0]);
}
/*
* au_add_user_method
* return: none
* class(in): class object
* returnval(out): return value of this method
* name(in):
* password(in):
*/
static void
au_add_user_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *name, DB_VALUE *password)
{
int error;
int exists;
MOP user;
const char *tmp = NULL;
if (name != NULL && DB_IS_STRING (name) && !DB_IS_NULL (name) && ((tmp = db_get_string (name)) != NULL))
{
if (intl_identifier_upper_string_size (tmp) >= DB_MAX_USER_LENGTH)
{
error = ER_USER_NAME_TOO_LONG;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
db_make_error (returnval, error);
return;
}
/*
* although au_set_password_encrypt will check this, check it out here before
* we bother creating the user object
*/
if (password != NULL && DB_IS_STRING (password) && !DB_IS_NULL (password) && (tmp = db_get_string (password))
&& strlen (tmp) > AU_MAX_PASSWORD_CHARS)
{
error = ER_AU_PASSWORD_OVERFLOW;
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, error, 0);
db_make_error (returnval, error);
}
else
{
user = au_add_user (db_get_string (name), &exists);
if (user == NULL)
{
/* return the error that was set */
db_make_error (returnval, er_errid ());
}
else if (exists)
{
error = ER_AU_USER_EXISTS;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, db_get_string (name));
db_make_error (returnval, error);
}
else
{
if (password != NULL && DB_IS_STRING (password) && !DB_IS_NULL (password))
{
error = au_set_password_encrypt (user, db_get_string (password));
if (error != NO_ERROR)
{
db_make_error (returnval, error);
}
else
{
db_make_object (returnval, user);
}
}
else
{
db_make_object (returnval, user);
}
}
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
db_make_error (returnval, error);
}
}
/*
* au_drop_user_method - Method interface for au_drop_user.
* return: none
* root(in):
* returnval(out): return value of this method
* name(in):
*/
static void
au_drop_user_method (MOP root, DB_VALUE *returnval, DB_VALUE *name)
{
int error;
DB_OBJECT *user = NULL;
db_make_null (returnval);
if (Au_dba_user != NULL && !au_is_dba_group_member (Au_user))
{
error = ER_AU_DBA_ONLY;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "drop_user");
db_make_error (returnval, error);
}
else
{
user = NULL;
if (name != NULL && DB_IS_STRING (name) && db_get_string (name) != NULL)
{
error = au_find_user_to_drop (db_get_string (name), &user);
if (error == NO_ERROR)
{
assert (user != NULL);
error = au_drop_user (user);
}
if (error != NO_ERROR)
{
db_make_error (returnval, error);
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
db_make_error (returnval, error);
}
}
}
/*
* au_find_user_method - Method interface to au_find_user.
* return: none
* class(in):
* returnval(out):
* name(in):
*/
static void
au_find_user_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *name)
{
MOP user;
int error = NO_ERROR;
db_make_null (returnval);
if (name != NULL && DB_IS_STRING (name) && !DB_IS_NULL (name) && db_get_string (name) != NULL)
{
user = au_find_user (db_get_string (name));
if (user != NULL)
{
db_make_object (returnval, user);
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
db_make_error (returnval, error);
}
}
/*
* au_add_member_method - Method interface to au_add_member.
* return: none
* user(in): user object
* returnval(out): return value of this method
* memval(in):
*/
static void
au_add_member_method (MOP user, DB_VALUE *returnval, DB_VALUE *memval)
{
int error = NO_ERROR;
MOP member;
if (memval != NULL)
{
member = NULL;
if (DB_VALUE_TYPE (memval) == DB_TYPE_OBJECT && !DB_IS_NULL (memval) && db_get_object (memval) != NULL)
{
member = db_get_object (memval);
}
else if (DB_IS_STRING (memval) && !DB_IS_NULL (memval) && db_get_string (memval) != NULL)
{
member = au_find_user (db_get_string (memval));
if (member == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
goto error;
}
}
if (member != NULL)
{
if (ws_is_same_object (user, Au_user) || au_is_dba_group_member (Au_user))
{
error = au_add_member (user, member);
}
else
{
error = ER_AU_NOT_OWNER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS));
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
error:
if (error == NO_ERROR)
{
db_make_null (returnval);
}
else
{
db_make_error (returnval, error);
}
}
/*
* au_drop_member_method - Method interface for au_drop_member.
* return: none
* user(in): user object
* returnval(in): return value of this method
* memval(in):
*/
static void
au_drop_member_method (MOP user, DB_VALUE *returnval, DB_VALUE *memval)
{
int error = NO_ERROR;
MOP member;
if (memval != NULL)
{
member = NULL;
if (DB_VALUE_TYPE (memval) == DB_TYPE_OBJECT && !DB_IS_NULL (memval) && db_get_object (memval) != NULL)
{
member = db_get_object (memval);
}
else if (DB_IS_STRING (memval) && !DB_IS_NULL (memval) && db_get_string (memval) != NULL)
{
member = au_find_user (db_get_string (memval));
if (member == NULL)
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
goto error;
}
}
if (member != NULL)
{
if (ws_is_same_object (user, Au_user) || au_is_dba_group_member (Au_user))
{
error = au_drop_member (user, member);
}
else
{
error = ER_AU_NOT_OWNER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, MSGCAT_GET_GLOSSARY_MSG (MSGCAT_GLOSSARY_CLASS));
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
error:
if (error == NO_ERROR)
{
db_make_null (returnval);
}
else
{
db_make_error (returnval, error);
}
}
/*
* au_set_password_method - Method interface for au_set_password_encrypt.
* return: none
* user(in): user object
* returnval(out): return value of this method
* password(in): new password
*/
static void
au_set_password_method (MOP user, DB_VALUE *returnval, DB_VALUE *password)
{
int error;
const char *string = NULL;
db_make_null (returnval);
if (password != NULL)
{
if (DB_IS_STRING (password) && !DB_IS_NULL (password))
{
string = db_get_string (password);
}
error = au_set_password_encrypt (user, string);
if (error != NO_ERROR)
{
db_make_error (returnval, error);
}
}
else
{
error = ER_AU_INVALID_PASSWORD;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0);
db_make_error (returnval, error);
}
}
/*
* au_set_password_encoded_method - Method interface for setting
* encoded passwords.
* return: none
* user(in): user object
* returnval(out): return value of this object
* password(in): new password
*
* Note: We don't check for the 8 character limit here because this is intended
* to be used only by the schema generated by unloaddb. For this
* application, the password length was validated when it was first
* created.
*/
static void
au_set_password_encoded_method (MOP user, DB_VALUE *returnval, DB_VALUE *password)
{
int error;
const char *string = NULL;
db_make_null (returnval);
if (password != NULL)
{
if (DB_IS_STRING (password))
{
if (DB_IS_NULL (password))
{
string = NULL;
}
else
{
string = db_get_string (password);
}
}
error = au_set_password_encrypt (user, string, 0, ENCODE_PREFIX_DES);
if (error != NO_ERROR)
{
db_make_error (returnval, error);
}
}
else
{
error = ER_AU_INVALID_PASSWORD;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0);
db_make_error (returnval, error);
}
}
/*
* au_set_password_encoded_sha1_method - Method interface for setting sha1/2 passwords.
* return: none
* user(in): user object
* returnval(out): return value of this object
* password(in): new password
*
* Note: We don't check for the 8 character limit here because this is intended
* to be used only by the schema generated by unloaddb. For this
* application, the password length was validated when it was first
* created.
*/
static void
au_set_password_encoded_sha1_method (MOP user, DB_VALUE *returnval, DB_VALUE *password)
{
int error;
const char *string = NULL;
db_make_null (returnval);
if (password != NULL)
{
if (DB_IS_STRING (password))
{
if (DB_IS_NULL (password))
{
string = NULL;
}
else
{
string = db_get_string (password);
}
}
/* in case of SHA2, prefix is not stripped */
if (string != NULL && IS_ENCODED_SHA2_512 (string))
{
error = au_set_password_encrypt (user, string + 1 /* 1 for prefix */, 0, ENCODE_PREFIX_SHA2_512);
}
else
{
error = au_set_password_encrypt (user, string, 0, ENCODE_PREFIX_SHA1);
}
if (error != NO_ERROR)
{
db_make_error (returnval, error);
}
}
else
{
error = ER_AU_INVALID_PASSWORD;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 0);
db_make_error (returnval, error);
}
}
/*
* au_describe_user_method() - Method interface to au_dump_user.
* Can only be called when using the csql
* interpreter since it dumps to stdout
* return: none
* user(in): user object
* returnval(out): return value of this method
*/
static void
au_describe_user_method (MOP user, DB_VALUE *returnval)
{
db_make_null (returnval);
if (user != NULL)
{
au_dump_user (user, stdout);
}
}
/*
* au_describe_root_method() - Method interface for authorization dump
* utilities
* return: none
* class_mop(in): class object
* returnval(out): return value of this method
* info(in):
*
* Note: This should be conditionalized so it knows what kind of environment
* this is (csql, esql). For now this is documented to
* only work within csql because it dumps to stdout.
* There are some hidden parameters that trigger other dump routines.
* This is a convenient hook for these things until we
* have a more formal way to call them (if we ever do). These
* are not documented in the user manual.
*/
static void
au_describe_root_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *info)
{
db_make_null (returnval);
if (info == NULL)
{
au_dump ();
}
else
{
/*
* temporary, pass this through for older databases that still
* have the "info" method pointing to this function
*/
au_info_method (class_mop, returnval, info);
}
}
/*
* au_info_method() - Method interface for authorization dump utilities.
* return: none
* class_mop(in): class object
* returnval(out): return value of this method
* info(in):
*
* Note: This should be conditionalized so it knows what kind of environment
* this is (csql, esql).
* For now this is documented to only work within csql because it dumps
* to stdout.
* There are some hidden parameters that trigger other dump routines.
* This is a convenient hook for these things until we
* have a more formal way to call them (if we ever do). These
* are not documented in the user manual.
*/
static void
au_info_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *info)
{
db_make_null (returnval);
if (info != NULL && DB_IS_STRING (info) && !DB_IS_NULL (info) && db_get_string (info) != NULL)
{
/* this dumps stuff to stdout */
help_print_info (db_get_string (info), stdout);
}
}
/*
* au_login_method - Method interface to au_login.
* return: none
* class_mop(in): class object
* returnval(out): return value of this method
* user(in): user name
* password(in): password
*/
static void
au_login_method (MOP class_mop, DB_VALUE *returnval, DB_VALUE *user, DB_VALUE *password)
{
int error = NO_ERROR;
char *user_name;
if (user != NULL)
{
if (DB_IS_STRING (user) && !DB_IS_NULL (user) && db_get_string (user) != NULL)
{
if (password != NULL && DB_IS_STRING (password))
{
error = au_login (db_get_string (user), db_get_string (password), false);
}
else
{
error = au_login (db_get_string (user), NULL, false);
}
}
}
else
{
error = ER_AU_INVALID_USER;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
if (error == NO_ERROR)
{
user_name = db_get_user_name ();
tm_Tran_invalidate_snapshot = 1;
error = clogin_user (user_name);
if (error == NO_ERROR)
{
db_make_null (returnval);
}
else
{
db_make_error (returnval, error);
}
db_string_free (user_name);
}
else
{
db_make_error (returnval, error);
}
}
/*
* au_change_owner_method - Method interface to au_change_owner
* return: none
* obj(in): class whose owner is to change
* returnval(out): return value of this method
* class(in):
* owner(in): new owner
*/
static void
au_change_owner_method (MOP obj, DB_VALUE *return_val, DB_VALUE *class_val, DB_VALUE *owner_val)
{
MOP class_mop = NULL;
SM_CLASS *class_ = NULL;
MOP *sub_partitions = NULL;
MOP owner_mop = NULL;
const char *class_name = NULL;
const char *owner_name = NULL;
char new_class_name[DB_MAX_IDENTIFIER_LENGTH] = {'\0', };
int is_partition = DB_NOT_PARTITIONED_CLASS;
bool has_savepoint = false;
int i;
int error = NO_ERROR;
if (!return_val || !class_val || !owner_val)
{
ERROR_SET_WARNING (error, ER_AU_INVALID_ARGUMENTS);
db_make_error (return_val, error);
return;
}
if (!DB_IS_STRING (class_val) || (class_name = db_get_string (class_val)) == NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_AU_INVALID_CLASS, "");
db_make_error (return_val, error);
return;
}
if (!DB_IS_STRING (owner_val) || (owner_name = db_get_string (owner_val)) == NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_AU_INVALID_USER, "");
db_make_error (return_val, error);
return;
}
/* We cannot change the schema of a class by using synonym names. */
if (db_find_synonym (class_name) != NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_LC_UNKNOWN_CLASSNAME, class_name);
db_make_error (return_val, error);
return;
}
else
{
ASSERT_ERROR ();
if (er_errid () == ER_SYNONYM_NOT_EXIST)
{
er_clear ();
}
else
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
}
class_mop = sm_find_class (class_name);
if (class_mop == NULL)
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
owner_mop = au_find_user (owner_name);
if (owner_mop == NULL)
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
error = au_fetch_class_force (class_mop, &class_, AU_FETCH_UPDATE);
if (error != NO_ERROR)
{
ASSERT_ERROR_AND_SET (error);
return;
}
/* To change the owner of a system class is not allowed. */
if (sm_issystem (class_))
{
ERROR_SET_ERROR_1ARG (error, ER_AU_CANT_ALTER_OWNER_OF_SYSTEM_CLASS, "");
db_make_error (return_val, error);
return;
}
/* When changing to the same owner, a No-Operation is performed. */
if (ws_is_same_object (class_->owner, owner_mop))
{
return;
}
/* When changing the owner of a class, the synonym name cannot be changed to be the same as the class name. */
snprintf (new_class_name, DB_MAX_IDENTIFIER_LENGTH, "%s.%s", owner_name, sm_remove_qualifier_name (class_name));
if (db_find_synonym (new_class_name) != NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_SYNONYM_ALREADY_EXIST, new_class_name);
db_make_error (return_val, error);
return;
}
else
{
ASSERT_ERROR ();
if (er_errid () == ER_SYNONYM_NOT_EXIST)
{
er_clear ();
}
else
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
}
/* When changing the owner of a class, the class name cannot be changed to be the same as the class name. */
if (db_find_class (new_class_name) != NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_LC_CLASSNAME_EXIST, new_class_name);
db_make_error (return_val, error);
return;
}
else
{
ASSERT_ERROR ();
if (er_errid () == ER_LC_UNKNOWN_CLASSNAME)
{
er_clear ();
}
else
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
}
error = au_change_class_owner (class_mop, owner_mop);
if (error != NO_ERROR)
{
ASSERT_ERROR ();
db_make_error (return_val, error);
}
}
/*
* au_change_trigger_owner_method - Method interface to au_change_trigger_owner
* return: none
* obj(in):
* returnval(out): return value of this method
* trigger(in): trigger whose owner is to change
* owner(in): new owner
*/
void
au_change_trigger_owner_method (MOP obj, DB_VALUE *return_val, DB_VALUE *trigger_val, DB_VALUE *owner_val)
{
MOP trigger_mop = NULL;
MOP owner_mop = NULL;
const char *trigger_name = NULL;
const char *owner_name = NULL;
int error = NO_ERROR;
if (!return_val || !trigger_val || !owner_val)
{
ERROR_SET_WARNING (error, ER_OBJ_INVALID_ARGUMENTS);
db_make_error (return_val, error);
return;
}
if (!DB_IS_STRING (trigger_val) || (trigger_name = db_get_string (trigger_val)) == NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_TR_TRIGGER_NOT_FOUND, "");
db_make_error (return_val, error);
return;
}
if (!DB_IS_STRING (owner_val) || (owner_name = db_get_string (owner_val)) == NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_AU_INVALID_USER, "");
db_make_error (return_val, error);
return;
}
trigger_mop = tr_find_trigger (trigger_name);
if (trigger_mop == NULL)
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
owner_mop = au_find_user (owner_name);
if (owner_mop == NULL)
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
error = au_change_trigger_owner (trigger_mop, owner_mop);
if (error != NO_ERROR)
{
ASSERT_ERROR ();
db_make_error (return_val, error);
}
}
/*
* au_get_owner_method - Method interface to au_change_owner
* return: none
* obj(in):
* returnval(out): return value of this method
* class(in): class object
*/
static void
au_get_owner_method (MOP obj, DB_VALUE *returnval, DB_VALUE *class_)
{
MOP user;
MOP classmop;
int error = NO_ERROR;
db_make_null (returnval);
if (class_ != NULL && DB_IS_STRING (class_) && !DB_IS_NULL (class_) && db_get_string (class_) != NULL)
{
classmop = sm_find_class (db_get_string (class_));
if (classmop != NULL)
{
user = au_get_class_owner (classmop);
if (user != NULL)
{
db_make_object (returnval, user);
}
else
{
assert (er_errid () != NO_ERROR);
error = er_errid ();
}
}
else
{
error = ER_AU_INVALID_CLASS;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, db_get_string (class_));
}
}
else
{
error = ER_AU_INVALID_CLASS;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
if (error != NO_ERROR)
{
db_make_error (returnval, error);
}
}
/*
* au_check_authorization_method -
* return: none
* obj(in):
* returnval(out): return value of this method
* class(in):
* auth(in):
*/
static void
au_check_authorization_method (MOP obj, DB_VALUE *returnval, DB_VALUE *class_, DB_VALUE *auth)
{
MOP classmop;
int error = NO_ERROR;
db_make_null (returnval);
if (class_ != NULL && DB_IS_STRING (class_) && !DB_IS_NULL (class_) && db_get_string (class_) != NULL)
{
classmop = sm_find_class (db_get_string (class_));
if (classmop != NULL)
{
error = au_check_class_authorization (classmop, (DB_AUTH) db_get_int (auth));
db_make_int (returnval, (error == NO_ERROR) ? true : false);
}
else
{
error = ER_AU_INVALID_CLASS;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, db_get_string (class_));
}
}
else
{
error = ER_AU_INVALID_CLASS;
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, error, 1, "");
}
}
/*
* au_change_sp_owner_method -
* return: none
* obj(in):
* returnval(in):
* sp(in):
* owner(in):
*/
static void
au_change_sp_owner_method (MOP obj, DB_VALUE *returnval, DB_VALUE *sp, DB_VALUE *owner)
{
MOP user, sp_mop;
int error;
int ok = 0;
db_make_null (returnval);
if (sp != NULL && DB_IS_STRING (sp) && !DB_IS_NULL (sp) && db_get_string (sp) != NULL)
{
if (owner != NULL && DB_IS_STRING (owner) && !DB_IS_NULL (owner) && db_get_string (owner) != NULL)
{
sp_mop = jsp_find_stored_procedure (db_get_string (sp), DB_AUTH_NONE);
if (sp_mop != NULL)
{
user = au_find_user (db_get_string (owner));
if (user != NULL)
{
error = au_change_sp_owner_with_transfer_privileges (NULL, sp_mop, user);
if (error == NO_ERROR)
{
ok = 1;
}
}
}
}
else
{
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_AU_INVALID_USER, 1, "");
}
}
else
{
er_set (ER_WARNING_SEVERITY, ARG_FILE_LINE, ER_SP_NOT_EXIST, 1, "");
}
if (!ok)
{
db_make_error (returnval, er_errid ());
}
}
/*
* au_change_serial_owner_method() - Method interface to au_change_serial_owner
* return: none
* obj(in): class whose owner is to change
* returnval(out): return value of this method
* serial(in): serial name
* owner(in): new owner
*/
static void
au_change_serial_owner_method (MOP obj, DB_VALUE *return_val, DB_VALUE *serial_val, DB_VALUE *owner_val)
{
MOP serial_class_mop = NULL;
MOP serial_mop = NULL;
DB_IDENTIFIER serial_obj_id;
MOP owner_mop = NULL;
const char *serial_name = NULL;
char user_specified_serial_name[DB_MAX_SERIAL_NAME_LENGTH] = { '\0' };
const char *owner_name = NULL;
int error = NO_ERROR;
if (!return_val || !serial_val || !owner_val)
{
ERROR_SET_WARNING (error, ER_OBJ_INVALID_ARGUMENTS);
db_make_error (return_val, error);
return;
}
if (!DB_IS_STRING (serial_val) || (serial_name = db_get_string (serial_val)) == NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_OBJ_INVALID_ARGUMENT, "");
db_make_error (return_val, error);
return;
}
if (!DB_IS_STRING (owner_val) || (owner_name = db_get_string (owner_val)) == NULL)
{
ERROR_SET_WARNING_1ARG (error, ER_AU_INVALID_USER, "");
db_make_error (return_val, error);
return;
}
serial_class_mop = sm_find_class (CT_SERIAL_NAME);
sm_user_specified_name_for_serial (serial_name, user_specified_serial_name, DB_MAX_SERIAL_NAME_LENGTH);
serial_mop = do_get_serial_obj_id (&serial_obj_id, serial_class_mop, user_specified_serial_name);
if (serial_mop == NULL)
{
ERROR_SET_ERROR_1ARG (error, ER_QPROC_SERIAL_NOT_FOUND, user_specified_serial_name);
db_make_error (return_val, error);
return;
}
owner_mop = au_find_user (owner_name);
if (owner_mop == NULL)
{
ASSERT_ERROR_AND_SET (error);
db_make_error (return_val, error);
return;
}
error = au_change_serial_owner (serial_mop, owner_mop, false);
if (error != NO_ERROR)
{
ASSERT_ERROR ();
db_make_error (return_val, error);
}
}
/*
* qo_set_cost () - csql method interface to qo_set_cost_fn()
* return: nothing
* target(in): The target of the method; we don't care
* result(in): The result returned by the method; we don't care
* plan(in): The plan type to get jacked
* cost(in): The new cost for that plan type
*
* Note: This should get registered in the schema as
*
* alter class foo
* add class method opt_set_cost(string, string)
* function qo_set_cost;
*
* No libraries or other files are required, since this will
* always be linked in to the base executable. Once linked, you
* should be able to do things like
*
* call opt_set_cost("iscan", "0") on class foo
*
* from csql
*/
static void
qo_set_cost (DB_OBJECT *target, DB_VALUE *result, DB_VALUE *plan, DB_VALUE *cost)
{
const char *plan_string;
const char *cost_string;
switch (DB_VALUE_TYPE (plan))
{
case DB_TYPE_STRING:
case DB_TYPE_CHAR:
plan_string = db_get_string (plan);
break;
default:
plan_string = "unknown";
break;
}
switch (DB_VALUE_TYPE (cost))
{
case DB_TYPE_STRING:
case DB_TYPE_CHAR:
cost_string = db_get_string (cost);
break;
default:
cost_string = "d";
break;
}
/*
* This relies on the fact that qo_plan_set_cost_fn is returning a
* CONST string. That way we don't need to dup it, and therefore we
* won't leak it when the return value is discarded.
*/
plan_string = qo_plan_set_cost_fn (plan_string, cost_string[0]);
if (plan_string != NULL)
{
db_make_string (result, plan_string);
}
else
{
er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_GENERIC_ERROR, 0);
db_make_error (result, ER_GENERIC_ERROR);
}
}
/*
* get_attribute_number - attribute number of the given attribute/class
* return:
* arg1(in):
* arg2(in):
*/
void
get_attribute_number_method (DB_OBJECT *target, DB_VALUE *result, DB_VALUE *attr_name)
{
int attrid, shared;
DB_DOMAIN *dom;
db_make_null (result);
if (DB_VALUE_TYPE (attr_name) != DB_TYPE_STRING)
{
return;
}
/* we will only look for regular attributes and not class attributes. this is a limitation of this method. */
if (sm_att_info (target, db_get_string (attr_name), &attrid, &dom, &shared, 0 /* non-class attrs */ )
< 0)
{
return;
}
db_make_int (result, attrid);
}
/*
* dbmeth_class_name() -
* return: None
* self(in): Class object
* result(out): DB_VALUE for a class name
*
* Note: Position of function arguments must be kept
* for pre-defined function pointers(au_static_links)
*/
static void
dbmeth_class_name (DB_OBJECT *self, DB_VALUE *result)
{
const char *cname;
cname = db_get_class_name (self);
/*
* Make a string and clone it so that it won't become invalid if the
* underlying class object that gave us the string goes away. Of
* course, this gives the responsibility for freeing the cloned
* string to someone else; is anybody accepting it?
*/
db_make_string (result, cname);
}
/*
* dbmeth_print() -
* return: None
* self(in): Class object
* result(out): NULL value
* msg(in): DB_VALUE for a message
*
* Note: Position of function arguments must be kept
* for pre-defined function pointers(au_static_links)
*/
static void
dbmeth_print (DB_OBJECT *self, DB_VALUE *result, DB_VALUE *msg)
{
db_value_print (msg);
printf ("\n");
db_make_null (result);
}