4
When trying to optimize some darlings not to depend on PHP to do something that could come ready from the database, I was trying to adapt the two routines below in the form of functions mysql:
function encode( $input, $index ) {
$base = strlen( $index );
$input += pow( $base, 4 );
$output = '';
for( $i = floor( log( $input, $base ) ); $i >= 0; $i-- ) {
$bcp = bcpow( $base, $i );
$start = floor( $input / $bcp ) % $base;
$output .= substr( $index, $start, 1 );
$input = $input - ( $start * $bcp );
}
return $output;
}
And:
function decode( $input, $index ) {
$base = strlen( $index );
$output = 0;
$length = strlen( $input ) - 1;
for( $i = 0; $i <= $length; $i++ ) {
$bcpow = bcpow( $base, $length - $i );
$output += strpos( $index, substr( $input, $i, 1 ) ) * $bcpow;
}
$output -= pow( $base, 4 );
$output = sprintf( '%F', $output );
$output = substr( $output, 0, strpos( $output, '.' ) );
return (int) $output;
}
Are functions that encode a integer in a string and vice versa, a Alphaid, almost like the one on Youtube.
As until the present time I had never created a Function from Mysql, I read the manual (which is not exactly user friendly) and arrived, at least as to Function coding, therein:
DROP FUNCTION IF EXISTS ENCODE_ALPHAID;
DELIMITER $$
CREATE FUNCTION ENCODE_ALPHAID( input integer ) RETURNS CHAR( 6 ) DETERMINISTIC
BEGIN
DECLARE output CHAR( 6 );
DECLARE letters CHAR( 62 );
DECLARE base TINYINT( 2 );
DECLARE iterator TINYINT( 2 );
DECLARE bcp CHAR( 9 );
DECLARE start TINYINT( 2 );
SET output = '';
SET letters = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
SET base = CHAR_LENGTH( letters );
SET input = input + POW( base, 4 );
SET iterator = FLOOR( LOG( base, input ) );
ENCODING: LOOP
SET bcp = POW( base, iterator );
SET start = FLOOR( input / bcp ) % base + 1;
SET output = CONCAT( output, SUBSTR( letters, start, 1 ) );
SET input = input - ( start * bcp );
SET iterator = iterator-1;
IF iterator < 0 THEN LEAVE ENCODING; END IF;
END LOOP ENCODING;
RETURN output;
END $$
DELIMITER ;
The routine was successfully created but has some problems:
- The original PHP routine codes correctly to the maximum possible value, described by the constant PHP_INT_MAX (2147483647), but the encoding for Mysql does not. At some point, which I could not fully debug, the encoding apparently stops, and the darlings do not return data.
- As far as coding works, it always acts "one forward". For example, codify the whole 2, instead of returning to the expected baaac is returning baaad
As for the decoding function:
DROP FUNCTION IF EXISTS DECODE_ALPHAID;
DELIMITER $$
CREATE FUNCTION DECODE_ALPHAID( input integer ) RETURNS INTEGER( 10 ) DETERMINISTIC
BEGIN
DECLARE output INT( 10 );
DECLARE letters CHAR( 62 );
DECLARE base TINYINT( 1 );
DECLARE length TINYINT( 1 );
DECLARE iterator TINYINT( 1 );
DECLARE bcp CHAR( 9 );
DECLARE dot CHAR( 1 );
SET output = 0;
SET letters = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
SET base = CHAR_LENGTH( letters );
SET length = CHAR_LENGTH( input ) - 1;
SET iterator = 0;
SET dot = '.';
ENCODING: LOOP
SET bcp = POW( base, length - iterator );
SET output = output + LOCATE( SUBSTR( input, iterator, 1 ), letters ) * bcp;
SET iterator = iterator+1;
IF iterator <= length THEN LEAVE ENCODING; END IF;
END LOOP ENCODING;
SET output = ( output - POW( base, 4 ) ) + 0.0;
SET output = SUBSTR( output, 0, LOCATE( dot, output ) );
RETURN output;
END $$
DELIMITER ;
It doesn’t even decode and, I believe, it’s by the way that the original author of the functions in PHP operated the results, formatting the mathematical calculus to float, operating as string and converting back to integer I lacked the knowledge to adapt correctly.
Even if the real need of the project is to have a unique textual representation of the registry ID, doing directly by Mysql I can avail myself of larger types, such as BIGINT, and have 9,223,372,036,854,775,807 combinations, one for each record.
– Bruno Augusto
The characters were missing:
~!@$*()-_+=|,.
, that wouldn’t be the problem?– Ivan Ferrer
Wouldn’t it be better to use the own Mysql method for that? Or that.
– Ivan Ferrer
I didn’t know there were native functions for this. I could then, in this case, do
ENCRYPT( \
c`. `Cid`, 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ), porque está retornando
NULL`. And using AES_ENCRYPT, since the other is deprecated I can’t see what returns because it appears Binary in the GUI I use– Bruno Augusto
@Brunoaugusto Base64 is not good for what you want (you have Mysql 5.6 on)? Or is it compatible with something already existing?
– Bacco
No, it is not to maintain compatibility with anything, it is only a feature of the project in which a certain thing, well already structure, which multiple users can have multiple "copies", must have a textual representation (letters and numbers only). Most plausible to me by the time I decided to carry out these duties, was a Alphaid under the primary key
– Bruno Augusto