Salesforce判断字符串是否为合法Id的规则

在去年年初,我们曾经讨论过Salesforce 15位ID与18位ID的话题(《关于salesforce的15位id与18位id》)。
那时候简单介绍了Salesforce的Id的组成,比如头三位为prefix,4到6位为instance code,校检位,18位ID的特性是case safe而不是大小写不敏感,等等。
那么有没有想过,Salesforce是如何知道某个字符串是不是合法的ID的呢?

虽然Apex里有Id与String两种数据类型,但是两者之间的关系却是如此暧昧与纠缠不清。
很多时候本应当使用Id型变量储存Id值,我们用String型变量去储存,然而也不会出问题。
再比如说,在SOQL中,我们在where语句中可以这么写…WHERE Id = ‘0016F000035LFXo ‘…干脆就是用的字符串。
如果是在Apex中,我们也可以使用变量…WHERE Id =: myId …,这里的变量myId无论是Id型还是String型也都不会有问题。所以粗略的看,似乎当作是一回事也没关系。

但是,如果我将字符串”ABCDEFG”赋值给ID型的变量,会怎么样呢?
如我们所料,会报异常,“ System.StringException: Invalid id: ABCDEFG ”。
这说明ID数据类型还是会对Id做合法性检查。
所以引出了最开始的问题,Salesforce是如何知道这个字符串是不是合法的ID的呢?

首先可以排除掉的可能性是Salesforce真的用这个字符串去数据库查一下。因为无论从性价比还是可行性上看,不会有哪个产品经理会同意这么做。

那么,既然Salesforce Id有文章开头提到的各种规则。
接来下比较容易想到的可能性是Salesforce使用了一套很复杂的规则来判断Id是否合法。
比如说

  • 判断长度是否为15位到18位
  • 判断头三位是不是已经存在的prefix
  • 判断4到6位是否是本org的instance code
  • 7到15位是否符合Id生成规则
  • 16到18位是否符合前15位的计算结果
  • 整体是否有非法字符

应该是一套足够严格的规则了。接下来,让我们做一组实验来一一验证。
首先在匿名块执行如下代码。

String test = '0016F000035LFXo'; // Replace with your org's record Id, valid one
try{
    Id myId = test;
} catch(Exception e) {
    System.debug(e);
}
if(test instanceof id) {
	System.debug('Yes');  
} else {
    System.debug('No');  
}

不出所料,结果为没有异常,Yes。毕竟使用的是合法的Id。
接下来逐条验证。
1. 将test变量中的值,在最末加一个“1”,成为” 0016F000035LFXo1 “。执行匿名块。结果为有异常(System.StringException: Invalid id: 0016F000035LFXo1),No。 同样的,使用18位版本Id末尾加“1”,得到了相同的结果。确实有位数判断。
2. 将test变量中的值,头三位改成“ZZZ”,成为“ZZZ6F000035LFXo”。
结果为有异常(System.StringException: Invalid id: ZZZ6F000035LFXo),No。说明确实有prefix检查,但是我不服气的。每个org有哪些已经使用的prefix一定不一样,秉着Salesforce不可能去查表的原则,我确定挑战此规则。
2改.
将test变量中的值,头三位改成“0ZZ”,成为“0ZZ6F000035LFXo”。
结果为无异常,Yes。OK,说明检查的重点在第一位,我要找到它的边界,所以我坚持不懈的尝试,终于找到边界是小写的“z”,这样的话,第一位的范围是[0-9 a-z]。
3.
将test变量中的值,接着2改的结果,将4到6位改成“ZZZ”,成为“zZZZZZ00035LFXo”。 结果为有异常,No。 说明4到6位的检查也是存在的。接下来仍然本着不服的精神,进行了逐位的探索与尝试。
3改. 将4到6位中的第六位改回0,成为 “zZZZZ000035LFXo” 。结果无异常,Yes。根据尝试结果,第六位如果不是0都会报错。所以规则应该只是检查第六位是否为0。
4.
将test变量中的值,接着3改的结果,将7到15位改成“Z”,成为“zZZZZ0ZZZZZZZZZ”。 结果有异常,No。还是不服,继续挑战。
4改. 这次运气比较好,一次就试出来了。将第七位改回0,成为 “zZZZZ00ZZZZZZZZ”。结果无异常,Yes。根据尝试结果,第七位不是0都会报错。所以规则应该只是检查第七位是否为0.(与第六位一起是传说中的保留位?)
5. 将test变量中的值, 接着4改的结果,将所有大写Z换成$,成为“z$$$$00$$$$$$$$”, 结果无异常,Yes。说明没有字符数字以外字符的检查。
6. 将test变量中的值, 接着5的结果,在末尾加三个“$”,使之达到18位,成为“
z$$$$00$$$$$$$$$$$”,结果无异常,Yes。说明。。。后三位和前面也没有计算关系检查。

总结一下,Salesforce对Id的判定是根据如下规则:
1. 第一位必须是0-9, a-z
2. 第六位,第七位必须为0
3. 整体必须15位或者18位
所以 “z$$$$00$$$$$$$$$$$” 这样的Id虽然事实上不会存在,但在法理上是属于合法的Id。

另外还需要注意一点,SOQL检索的时候,由于真的可以去数据库验证,所以只有位数验证。意味着,用15个或者18个$,也是可以正常检索的,只不过永远找不到对应的数据而已。

此外,好奇心强的同学一定还想知道,既然$都算合法字符,那么空白字符算不算合法的?
比如“z 00 ”(z[4个空格]00[8个空格])。
OK,让我们来试一下,不出所料,结果无异常,Yes。。。(耸肩)

《Salesforce判断字符串是否为合法Id的规则》有2个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据