← Back to team overview

maria-developers team mailing list archive

InnoDB blob for primary key

 

Hello Developers,
Hi this is sachin.Actually i was currently experimenting with with
blob uniques in innodb
there is three main problems
1.Unique blob
2.Blob Forigen key
3.Blob primary key

1. For blob unique we can simply store hash in unclustered index
2. Blob Forigen key i am currently working on it
3. Blob primary key :- for this i thought we create a 4 byte column
which stores the hash of blob primary key.Internally this column will work
as
primary key and key for clustered index. I already successufully tested
this
here is my output

MariaDB [sachin]> create table t4 (abc blob primary key);
Query OK, 0 rows affected (0.10 sec)

MariaDB [sachin]> insert into t4 values('sachin');
Query OK, 1 row affected (0.01 sec)

MariaDB [sachin]> insert into t4 values('sachin');
ERROR 1062 (23000): Duplicate entry 'sachin' for key 'PRIMARY'
MariaDB [sachin]> insert into t4 values('sachin setiya');
Query OK, 1 row affected (0.00 sec)

MariaDB [sachin]> insert into t4 values('sachin setiya');
ERROR 1062 (23000): Duplicate entry 'sachin setiya' for key 'PRIMARY'

MariaDB [sachin]> desc t4;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| abc   | blob | NO   | PRI | NULL    |       |
+-------+------+------+-----+---------+-------+
1 row in set (0.01 sec)

MariaDB [sachin]> select * from t4;
+---------------+
| abc           |
+---------------+
| sachin        |
| sachin setiya |
+---------------+
2 rows in set (0.01 sec)

@Sergei hi! Actually i invested arround 2 months in mariadb So for me now
it  does not matter either i got selected in gsoc i want to do work in
innodb blob unique from today.Please sir allow me to do this

I am including the patch file and t4.ibd and t4.frm file
Regards
sachin
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index dfce503..efd6f22 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3244,7 +3244,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
 	!(sql_field->charset= find_bin_collation(sql_field->charset)))
       DBUG_RETURN(TRUE);
 
-    /*
+    /*	
       Convert the default value from client character
       set into the column character set if necessary.
     */
@@ -3874,11 +3874,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
           if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
               Field::GEOM_POINT)
             column->length= MAX_LEN_GEOM_POINT_FIELD;
-	  if (!column->length)
-	  {
-	    my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
-	    DBUG_RETURN(TRUE);
-	  }
+//	  if (!column->length) //change
+//	  {
+//	    my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
+//	    DBUG_RETURN(TRUE);
+//	  }
 	}
 #ifdef HAVE_SPATIAL
 	if (key->type == Key::SPATIAL)
@@ -3992,9 +3992,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
       }
       else if (key_part_length == 0 && (sql_field->flags & NOT_NULL_FLAG))
       {
-	my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(),
-                 column->field_name.str);
-	  DBUG_RETURN(TRUE);
+//	my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(),
+//                 column->field_name.str);
+//	  DBUG_RETURN(TRUE);
       }
       if (key_part_length > file->max_key_part_length() &&
           key->type != Key::FULLTEXT)
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index c51deb0..f6e94af 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1315,7 +1315,7 @@ dict_table_add_to_cache(
 #define BIG_ROW_SIZE 1024
 
 	ut_ad(mutex_own(&(dict_sys->mutex)));
-
+	
 	dict_table_add_system_columns(table, heap);
 
 	table->cached = TRUE;
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 206038d..d8223d7 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -1251,7 +1251,7 @@ dict_table_open_on_name(
 Adds system columns to a table object. */
 UNIV_INTERN
 void
-dict_table_add_system_columns(
+dict_table_add_system_columns( //work
 /*==========================*/
 	dict_table_t*	table,	/*!< in/out: table */
 	mem_heap_t*	heap)	/*!< in: temporary heap */
@@ -1266,16 +1266,25 @@ dict_table_add_system_columns(
 	etc.) and as the last columns of the table memory object.
 	The clustered index will not always physically contain all
 	system columns. */
-
+//	dict_mem_table_add_col(table,heap,"DB_BLOB_HASH",DATA_INT
+//	,DATA_NOT_NULL,DATA_BLOB_HASH_LEN);
 	dict_mem_table_add_col(table, heap, "DB_ROW_ID", DATA_SYS,
 			       DATA_ROW_ID | DATA_NOT_NULL,
 			       DATA_ROW_ID_LEN);
 #if DATA_ROW_ID != 0
 #error "DATA_ROW_ID != 0"
 #endif
+//	dict_mem_table_add_col(table,heap,"DB_BLOB_HASH",DATA_SYS,
+//							DATA_BLOB_HASH|DATA_NOT_NULL,
+//							DATA_BLOB_HASH_LEN);
+	//just a rough trick to get it working
+	
+//	if(*table->name=='y'){
 	dict_mem_table_add_col(table, heap, "DB_TRX_ID", DATA_SYS,
 			       DATA_TRX_ID | DATA_NOT_NULL,
 			       DATA_TRX_ID_LEN);
+//	}
+	
 #if DATA_TRX_ID != 1
 #error "DATA_TRX_ID != 1"
 #endif
@@ -1310,7 +1319,11 @@ dict_table_add_to_cache(
 	ulint	row_len;
 
 	ut_ad(dict_lru_validate());
-
+//	bool x =false;//break
+//	if(x){
+//		dict_mem_table_add_col(table,heap,"DB_BLOB_HASH",DATA_INT
+//								,DATA_NOT_NULL,4);
+//	}
 	/* The lower limit for what we consider a "big" row */
 #define BIG_ROW_SIZE 1024
 
@@ -3075,7 +3088,7 @@ dict_index_build_internal_clust(
 	/* Copy the fields of index */
 	dict_index_copy(new_index, index, table, 0, index->n_fields);
 
-	if (dict_index_is_univ(index)) {
+	if (dict_index_is_univ(index)) { //work
 		/* No fixed number of fields determines an entry uniquely */
 
 		new_index->n_uniq = REC_MAX_N_FIELDS;
@@ -3124,7 +3137,7 @@ dict_index_build_internal_clust(
 							  DATA_ROLL_PTR),
 				   0);
 
-		for (i = 0; i < trx_id_pos; i++) {
+		for (i = 0; i < trx_id_pos; i++) {//work i think i need to do some stuff
 
 			ulint fixed_size = dict_col_get_fixed_size(
 				dict_index_get_nth_col(new_index, i),
diff --git a/storage/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc
index d6ed8ac..8cc59f8 100644
--- a/storage/xtradb/dict/dict0load.cc
+++ b/storage/xtradb/dict/dict0load.cc
@@ -2276,7 +2276,7 @@ dictionary cache.
 ibd_file_missing flag TRUE in the table object we return */
 UNIV_INTERN
 dict_table_t*
-dict_load_table(
+dict_load_table( //work for corruped table
 /*============*/
 	const char*	name,	/*!< in: table name in the
 				databasename/tablename format */
@@ -2337,7 +2337,7 @@ dict_load_table(
 		btr_pcur_close(&pcur);
 		mtr_commit(&mtr);
 		mem_heap_free(heap);
-
+		
 		return(NULL);
 	}
 
diff --git a/storage/xtradb/dict/dict0mem.cc b/storage/xtradb/dict/dict0mem.cc
index a4f6cd6..6cbe556 100644
--- a/storage/xtradb/dict/dict0mem.cc
+++ b/storage/xtradb/dict/dict0mem.cc
@@ -101,11 +101,11 @@ dict_mem_table_create(
 	memcpy(table->name, name, strlen(name) + 1);
 	table->is_system_db = dict_mem_table_is_system(table->name);
 	table->space = (unsigned int) space;
-	table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS);
-
+	table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS); //work
+	
 	table->cols = static_cast<dict_col_t*>(
 		mem_heap_alloc(heap,
-			       (n_cols + DATA_N_SYS_COLS)
+			       (n_cols + DATA_N_SYS_COLS)//work
 			       * sizeof(dict_col_t)));
 
 	ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index e5edf76..3a8dc91 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -5983,7 +5983,7 @@ ha_innobase::open(
 	ibool			par_case_name_set = FALSE;
 	char			par_case_name[FN_REFLEN];
 	dict_err_ignore_t	ignore_err = DICT_ERR_IGNORE_NONE;
-
+	ibool is_blob_primary_key=false;
 	DBUG_ENTER("ha_innobase::open");
 
 	UT_NOT_USED(mode);
@@ -6031,13 +6031,20 @@ ha_innobase::open(
 
 	/* Get pointer to a table object in InnoDB dictionary cache */
 	ib_table = dict_table_open_on_name(norm_name, FALSE, TRUE, ignore_err);
-
+	//int number_of_columns = dict_table_get_n_user_cols(ib_table);
+	//if(ib_table->)
+	if(ib_table){
+		int number_of_columns = dict_table_get_n_user_cols(ib_table);
+		if(!innobase_strcasecmp(ib_table->col_names,"DB_BLOB_HASH")){
+			is_blob_primary_key=true;
+			number_of_columns--;//stodo i think we need to add flag for blob primary key to make checking easier
+		}
 	if (ib_table
-	    && ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID)
-		 && table->s->stored_fields != dict_table_get_n_user_cols(ib_table))
+	    && ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID))
+		 && table->s->stored_fields != number_of_columns) //work
 		|| (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID)
 		    && (table->s->fields
-			!= dict_table_get_n_user_cols(ib_table) - 1)))) {
+			!= dict_table_get_n_user_cols(ib_table) - 1))) {
 		ib_logf(IB_LOG_LEVEL_WARN,
 			"table %s contains %lu user defined columns "
 			"in InnoDB, but %lu columns in MySQL. Please "
@@ -6054,7 +6061,7 @@ ha_innobase::open(
 		ib_table = NULL;
 		is_part = NULL;
 	}
-
+	}
 	if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt &&
 			  srv_pass_corrupt_table <= 1)) {
 		free_share(share);
@@ -6254,12 +6261,12 @@ ha_innobase::open(
 	/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 	primary_key = table->s->primary_key;
 	key_used_on_scan = primary_key;
-
+	if(!is_blob_primary_key){
 	if (!innobase_build_index_translation(table, ib_table, share)) {
 		  sql_print_error("Build InnoDB index translation table for"
 				  " Table %s failed", name);
 	}
-
+	}
 	/* Allocate a buffer for a 'row reference'. A row reference is
 	a string of bytes of length ref_length which uniquely specifies
 	a row in our table. Note that MySQL may also compare two row
@@ -6314,7 +6321,11 @@ ha_innobase::open(
 			for (uint i = 0; i < table->s->keys; i++) {
 				dict_index_t*	index;
 				index = innobase_get_index(i);
-				if (dict_index_is_clust(index)) {
+				if (dict_index_is_clust(index)) { //work
+				if(is_blob_primary_key){
+					ref_length=4; //hash length
+					continue;
+				}
 					ref_length =
 						 table->key_info[i].key_length;
 				}
@@ -7795,7 +7806,8 @@ build_template_field(
 
 	//ut_ad(field == table->field[i]);
 	ut_ad(clust_index->table == index->table);
-
+//work here we go 
+//todo it should get the next column defs
 	col = dict_table_get_nth_col(index->table, i);
 
 	templ = prebuilt->mysql_template + prebuilt->n_template++;
@@ -8138,7 +8150,8 @@ ha_innobase::build_template(
 					continue;
 				}
 			}
-
+				if(!innobase_strcasecmp(clust_index->fields->name,"DB_BLOB_HASH"))
+					i++;
 			build_template_field(prebuilt, clust_index, index,
 					     table, field, i);
 		}
@@ -11065,6 +11078,7 @@ create_table_def(
 	ulint		doc_id_col = 0;
 	ibool		has_doc_id_col = FALSE;
 	mem_heap_t*	heap;
+	bool is_blob_primary_key=false;
 
 	DBUG_ENTER("create_table_def");
 	DBUG_PRINT("enter", ("table_name: %s", table_name));
@@ -11126,6 +11140,12 @@ create_table_def(
 			table->fts->doc_col = doc_id_col;
 		}
 	} else {
+		if(form->key_info[0].key_part->length==0 && //change
+		form->key_info[0].key_part->key_type|MYSQL_TYPE_BLOB){
+			s_cols++;
+			is_blob_primary_key=true;
+		}
+				
 		table = dict_mem_table_create(table_name, 0, s_cols,
 					      flags, flags2);
 	}
@@ -11143,6 +11163,13 @@ create_table_def(
 		table->data_dir_path = NULL;
 	}
 	heap = mem_heap_create(1000);
+	//work
+	//add one more column for hash
+		
+	if(is_blob_primary_key){
+		dict_mem_table_add_col(table,heap,"DB_BLOB_HASH",
+	DATA_INT,1283,4);
+	}
 
 	for (i = 0; i < n_cols; i++) {
 		Field*	field = form->field[i];
@@ -11222,7 +11249,7 @@ create_table_def(
 			err = DB_ERROR;
 			goto error_ret;
 		}
-
+		
 		dict_mem_table_add_col(table, heap,
 			field->field_name,
 			col_type,
@@ -11347,7 +11374,7 @@ create_index(
 		the length of the key part versus the column. */
 
 		Field*	field = NULL;
-
+//work
 		for (ulint j = 0; j < form->s->fields; j++) {
 
 			field = form->field[j];
@@ -11396,7 +11423,12 @@ create_index(
 		}
 
 		field_lengths[i] = key_part->length;
-
+		if(form->key_info[0].key_part->length==0 && //change
+		form->key_info[0].key_part->key_type|MYSQL_TYPE_BLOB){
+			dict_mem_index_add_field(
+			index,"DB_BLOB_HASH", 0);
+			continue;
+		}
 		dict_mem_index_add_field(
 			index, key_part->field->field_name, prefix_len);
 	}
diff --git a/storage/xtradb/include/data0type.h b/storage/xtradb/include/data0type.h
index 111664b..0f510e8 100644
--- a/storage/xtradb/include/data0type.h
+++ b/storage/xtradb/include/data0type.h
@@ -147,6 +147,9 @@ be less than 256 */
 #define	DATA_ROLL_PTR	2	/* rollback data pointer: 7 bytes */
 #define DATA_ROLL_PTR_LEN 7
 
+//#define DATA_BLOB_HASH  3        // hash coloumn for blob primay key 
+//#define DATA_BLOB_HASH_LEN 4	//used as a clustered index 
+
 #define	DATA_N_SYS_COLS 3	/* number of system columns defined above */
 
 #define DATA_FTS_DOC_ID	3	/* Used as FTS DOC ID column */
diff --git a/storage/xtradb/que/que0que.cc b/storage/xtradb/que/que0que.cc
index e2dc023..076785d 100644
--- a/storage/xtradb/que/que0que.cc
+++ b/storage/xtradb/que/que0que.cc
@@ -1030,7 +1030,7 @@ que_thr_step(
 		que_node_print_info(node);
 	}
 #endif
-	if (type & QUE_NODE_CONTROL_STAT) {
+	if (type & QUE_NODE_CONTROL_STAT) { //improve
 		if ((thr->prev_node != que_node_get_parent(node))
 		    && que_node_get_next(thr->prev_node)) {
 
diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc
index d02e179..c58d7fb 100644
--- a/storage/xtradb/row/row0ins.cc
+++ b/storage/xtradb/row/row0ins.cc
@@ -137,7 +137,7 @@ row_ins_alloc_sys_fields(
 /*=====================*/
 	ins_node_t*	node)	/*!< in: insert node */
 {
-	dtuple_t*		row;
+	dtuple_t*		row;  //work
 	dict_table_t*		table;
 	mem_heap_t*		heap;
 	const dict_col_t*	col;
@@ -3118,7 +3118,7 @@ row_ins_index_entry_set_vals(
 
 	n_fields = dtuple_get_n_fields(entry);
 
-	for (i = 0; i < n_fields; i++) {
+	for (i = 0; i < n_fields; i++) {//see
 		dict_field_t*	ind_field;
 		dfield_t*	field;
 		const dfield_t*	row_field;
@@ -3169,8 +3169,8 @@ row_ins_index_entry_step(
 
 	ut_ad(dtuple_check_typed(node->row));
 
-	row_ins_index_entry_set_vals(node->index, node->entry, node->row);
-
+	row_ins_index_entry_set_vals(node->index, node->entry, node->row);//explore 
+//need to see who sets the entry in row
 	ut_ad(dtuple_check_typed(node->entry));
 
 	err = row_ins_index_entry(node->index, node->entry, thr);
@@ -3208,7 +3208,7 @@ row_ins_alloc_row_id_step(
 
 	/* Fill in row id value to row */
 
-	row_id = dict_sys_get_new_row_id();
+	row_id = dict_sys_get_new_row_id(); //work
 
 	dict_sys_write_row_id(node->row_id_buf, row_id);
 }
diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc
index 9427b20..b28e778 100644
--- a/storage/xtradb/row/row0mysql.cc
+++ b/storage/xtradb/row/row0mysql.cc
@@ -510,7 +510,15 @@ row_mysql_store_col_in_innobase_format(
 
 	return(buf);
 }
-
+//this is just dummy function
+int dummuy_hash(byte * ptr,int length){
+	int val=0;
+	for(int i=0;i<length;i++){
+		val =val*8+(int )*ptr;
+		ptr++;
+	}
+	return val;
+}
 /**************************************************************//**
 Convert a row in the MySQL format to a row in the Innobase format. Note that
 the function to convert a MySQL format key value to an InnoDB dtuple is
@@ -532,15 +540,22 @@ row_mysql_convert_row_to_innobase(
 	const mysql_row_templ_t*templ;
 	dfield_t*		dfield;
 	ulint			i;
-
+	ibool 			is_blob_primary_key=false;
+	ibool 			is_first_template=true;
 	ut_ad(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
-	ut_ad(prebuilt->mysql_template);
-
-	for (i = 0; i < prebuilt->n_template; i++) {
+	ut_ad(prebuilt->mysql_template);//work
+	if(!innobase_strcasecmp(prebuilt->table->col_names,"DB_BLOB_HASH")){
+		is_blob_primary_key =true;
+	}
+	for (i = 0; i < prebuilt->n_template; i++) { //change add one
 
 		templ = prebuilt->mysql_template + i;
+		if(is_blob_primary_key&&is_first_template){
+			dfield = dtuple_get_nth_field(row, i+1);
+			is_first_template=false;
+		}else{
 		dfield = dtuple_get_nth_field(row, i);
-
+		}
 		if (templ->mysql_null_bit_mask != 0) {
 			/* Column may be SQL NULL */
 
@@ -565,6 +580,17 @@ row_mysql_convert_row_to_innobase(
 next_column:
 		;
 	}
+	if(is_blob_primary_key){
+		//get the first field and set  the hash
+		dfield_t * hash_field=dtuple_get_nth_field(row,0);
+		dfield_t * blob_field=dtuple_get_nth_field(row,1);
+		byte * hash = static_cast<byte *>(mem_heap_zalloc(prebuilt->heap,4));
+		mach_write_to_4(hash,dummuy_hash((byte *)blob_field->data,blob_field->len));
+		//4 is hash length
+		hash_field->len=4;
+		hash_field->data=hash;
+		//hash_field->type
+	}
 
 	/* If there is a FTS doc id column and it is not user supplied (
 	generated by server) then assign it a new doc id. */
@@ -831,7 +857,7 @@ row_create_prebuilt(
 
 	prebuilt->search_tuple = dtuple_create(heap, search_tuple_n_fields);
 
-	ref = dtuple_create(heap, ref_len);
+	ref = dtuple_create(heap, ref_len);//work 
 
 	dict_index_copy_types(ref, clust_index, ref_len);
 
@@ -1057,7 +1083,7 @@ row_get_prebuilt_insert_row(
 
 	dict_table_copy_types(row, table);
 
-	ins_node_set_new_row(node, row);
+	ins_node_set_new_row(node, row);//explore
 
 	prebuilt->ins_graph = static_cast<que_fork_t*>(
 		que_node_get_parent(
@@ -1353,7 +1379,7 @@ row_insert_for_mysql(
 	row_get_prebuilt_insert_row(prebuilt);
 	node = prebuilt->ins_node;
 
-	row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec);
+	row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec);//debug
 
 	savept = trx_savept_take(trx);
 
diff --git a/storage/xtradb/row/row0row.cc b/storage/xtradb/row/row0row.cc
index be786f9..a1dd465 100644
--- a/storage/xtradb/row/row0row.cc
+++ b/storage/xtradb/row/row0row.cc
@@ -83,7 +83,7 @@ row_build_index_entry_low(
 			entry, dict_index_get_n_unique_in_tree(index));
 	}
 
-	for (i = 0; i < entry_len; i++) {
+	for (i = 0; i < entry_len; i++) { //explore need to see how it works for simple
 		const dict_field_t*	ind_field
 			= dict_index_get_nth_field(index, i);
 		const dict_col_t*	col

Attachment: t4.frm
Description: Binary data

Attachment: t4.ibd
Description: Binary data


Follow ups