--这是为 MySQL 编写的简易序列存储程序(一个函数)。
--在使用序列之前,需要通过往序列记录表中加入数值的方式初始化序列:
--INSERT INTO Sequence ('name...', 0);
--之后,就可以通过 nextval('name...') 函数来取得名为 name... 的序列新值。
--考虑到 update 自身的行锁能力。所以本序列程序具有很强的并发提供能力。
DROP TABLE IF EXISTS Sequence;
CREATE TABLE Sequence
(
name VARCHAR(32),
maxIndex INTEGER,
CONSTRAINT cst_Sequence_pk PRIMARY KEY (name, maxIndex)
) DEFAULT CHARACTER SET utf8
ENGINE InnoDB;
SET GLOBAL log_bin_trust_function_creators = 1;
DROP FUNCTION IF EXISTS nextval;
DELIMITER //
CREATE FUNCTION nextval(sequenceName VARCHAR(32))
RETURNS INTEGER
NOT DETERMINISTIC
CONTAINS SQL
/* ********** ********** ********** **********
This is a common sequence function. It is based on table Sequence.
This function will return new integer by given sequence name.
author: Shane Loo Li
version: 1.1.1, 2012-7-17 Tuesday Modified edition.
history:
1.1.0, 2012-7-14 Saturday Shane Loo Li New
1.1.1, 2012-7-17 Tuesday Shane Loo Li Modified wrong column name.
********** ********** ********** ********** */
BEGIN
DECLARE iMaxIndex INTEGER;
UPDATE Sequence SET maxIndex = maxIndex + 1 WHERE name = sequenceName;
SELECT maxIndex INTO iMaxIndex
FROM Sequence WHERE name = sequenceName;
RETURN iMaxIndex;
END
//
DELIMITER ;
|
/**
* 对于字符串分隔,在 Java 6.0 以内,都只提供了支持正则表达式的 split() 一套方法。
* 对于简单的分割,正则表达式消耗了一半以上的运算资源。先考虑大规模计算中频繁用
* 到的字符串分割,自制了一个方法,通过取出 char[] ,逐一判断是否是分割用的字符,
* 通过 {@link System#arraycopy(Object, int, Object, int, int)} 取出一个个字符
* 数组,生成字符串,存放进一个 {@link LinkedList} 里边。如果规模比较大,拟考虑
* 通过二重循环,用 String[] 作为结果收集器。
*/
static public List<String> splitSimpleString(String source, char gap)
{
List<String> result = new LinkedList<String>();
if (source == null) return result;
char[] sourceChars = source.toCharArray();
int startIndex = 0, index = -1;
while (index++ != sourceChars.length)
{
if (index == sourceChars.length || sourceChars[index] == gap)
{
char[] section = new char[index - startIndex];
System.arraycopy(sourceChars, startIndex,
section, 0, index - startIndex);
result.add(String.valueOf(section));
startIndex = index + 1;
}
}
return result;
}
|
/**
* Galaxy War Encyclopedia
* catalogue.js independently from 2012-4-14 Saturday 17:53:38 PM
* ---------- ---------- ---------- ----------
* Copyright(c) 2012-2022 Entertainment Ltd.
* E-mail: developer@gamecenternow.com
* ---------- ---------- ---------- ----------
* Galaxy War Encyclopedia is a detail of every game element.
*/
/**
* Program config.
*/
var config = {
// px, height per sub catalogue.
subHeight: 30,
// millis
smoothGap: 10,
// px
smoothStep: 2,
// millis
checkGap: 500
};
/**
* Record each catalogue is opened (true) or floded (false).
*/
var eachCatalogueStatus = { };
/**
* Record last opened catalogue page element's id
*/
var lastOpenedCatalogueId = null;
/**
* Lock is used to prevent the choas from multiple click.
*/
var lock = null;
/**
* Change sub catalogue. Change means open or fold.
* When click on a catalogue, this method will be invoked.
*/
var catalogueChange = function(catalogueId, type)
{
// Get sub catalogue element.
var subCatalogue = etm$(catalogueId + "-sub");
// Record element real height.
var realHeight = subCatalogue.getElementsByTagName("div").length * config.subHeight;
if (!(eachCatalogueStatus[catalogueId].realHeightStr))
{ eachCatalogueStatus[catalogueId].realHeightStr = realHeight + "px"; }
// Do different with SHOW and HIDE.
switch (type)
{
case catalogueChange.SHOW:
showSubCatalogue(catalogueId, subCatalogue, realHeight);
break;
case catalogueChange.HIDE:
hideSubCatalogue(catalogueId, subCatalogue, realHeight);
break;
}
};
catalogueChange.SHOW = { operation: "show" };
catalogueChange.HIDE = { operation: "hide" };
/**
* Open a sub catalogue area by catalogue id.
*/
var showSubCatalogue = function(catalogueId, subCatalogue, realHeight)
{
subCatalogue.style.height = "0px";
subCatalogue.hidden = false;
delete subCatalogue.hidden;
subCatalogue.style.display = "block";
var intervalCode =
"registerProcess(0, " + realHeight + ", \"" + catalogueId + "\", catalogueChange.SHOW);";
eachCatalogueStatus[catalogueId].threadId = setInterval(intervalCode, config.smoothGap);
};
/**
* Fold a sub catalogue area by catalogue id.
*/
var hideSubCatalogue = function(catalogueId, subCatalogue, realHeight)
{
subCatalogue.style.height = realHeight + "px";
var intervalCode =
"registerProcess(" + realHeight + ", 0, \"" + catalogueId + "\", catalogueChange.HIDE);";
eachCatalogueStatus[catalogueId].threadId = setInterval(intervalCode, config.smoothGap);
};
/**
* The effect on click at a catalogue
* This method will do differently, according to whether the clicked catalogue is opened.
* If it is opened, this method will fold it and clean "last opened" record.
* If it is not opened, this method will fold last opened catalogue, and open this one.
*/
var catalogueOnClick = function()
{
// If locked, do nothins.
if (lock) { return; } else { lock = true; }
var targetId = this.id.split("-")[0];
// If clicked catalogue has been opened.
if (eachCatalogueStatus[targetId].open)
{
// Hide it.
catalogueChange(targetId, catalogueChange.HIDE);
// Register an interval function to keep lock until finish hiding.
eachCatalogueStatus[targetId].checkThreadId =
setInterval("whenCheckHidingSelf(\"" + targetId + "\");", config.checkGap);
}
// If clicked catalogue is folded.
else
{
// If there is another catalogue is opened, fold it.
if (lastOpenedCatalogueId != null)
{ catalogueChange(lastOpenedCatalogueId, catalogueChange.HIDE); }
// Open this catalogue.
catalogueChange(targetId, catalogueChange.SHOW);
// Register an interval function to keep lock
// until finish opening this catalogue and folding last opened catalogue.
eachCatalogueStatus[targetId].checkThreadId =
setInterval("whenCheckOpenNew(\"" + targetId + "\");", config.checkGap);
}
};
/**
* The effect on click sub catalogue.
* Change the main page to the title content of the clicked sub catalogue.
*/
var subCatalogueOnClick = function()
{
var contentIframe = window.parent.document.getElementById("pagecontent");
contentIframe.src = this.title;
};
/**
* Register all click method etc.
*/
var catalogueInit = function()
{
var baseBody = etm$("catalogueBody");
var allCatalogue = baseBody.childNodes;
for (var index = -1; ++index != allCatalogue.length; )
{
var element = allCatalogue[index];
if (element.nodeType != 1) { continue; }
var targetId = element.id;
eachCatalogueStatus[targetId] = new Object();
eachCatalogueStatus[targetId].open = false;
etm$(targetId + "-main").onclick = catalogueOnClick;
var allSub = etm$(targetId + "-sub").childNodes;
for (var subIndex = -1; ++subIndex != allSub.length; )
{
var subElement = allSub[subIndex];
if (subElement.nodeType != 1) { continue; }
subElement.onclick = subCatalogueOnClick;
}
}
};
/**
* Smooth effect function.
*/
var registerProcess = function(start, end, catalogueId, type)
{
var heightStr = etm$(catalogueId + "-sub").style.height;
var realHeight = heightStr.substring(0, heightStr.length - 2) * 1;
if (start <= end && realHeight >= end || start >= end && realHeight <= end)
{
switch (type)
{
case catalogueChange.SHOW:
whenFinishShowing(catalogueId);
return;
case catalogueChange.HIDE:
whenFinishHiding(catalogueId);
return;
}
return;
}
if (start <= end && realHeight < end) { realHeight += config.smoothStep; }
else if (start >= end && realHeight > end) { realHeight -= config.smoothStep; }
etm$(catalogueId + "-sub").style.height = realHeight + "px";
};
/**
* Call back function when finish showing.
*/
var whenFinishShowing = function(catalogueId)
{
var threadId = eachCatalogueStatus[catalogueId].threadId;
if (threadId) { clearInterval(threadId); }
eachCatalogueStatus[catalogueId].open = true;
};
/**
* Call back function when finish hiding.
*/
var whenFinishHiding = function(catalogueId)
{
var threadId = eachCatalogueStatus[catalogueId].threadId;
if (threadId) { clearInterval(threadId); }
var subCatalogue = etm$(catalogueId + "-sub");
subCatalogue.style.display = "none";
subCatalogue.hidden = "hidden";
subCatalogue.style.height = eachCatalogueStatus[catalogueId].realHeightStr;
eachCatalogueStatus[catalogueId].open = false;
};
/**
* Keeping lock when changing one sub catalogue display state.
* This method is used to check if the changing process has been finished.
*/
var whenCheckHidingSelf = function(catalogueId)
{
// If hiding process hasn't been finished, return.
if (eachCatalogueStatus[catalogueId].open) { return; }
var checkThreadId = eachCatalogueStatus[catalogueId].checkThreadId;
if (checkThreadId) { clearInterval(checkThreadId); }
lastOpenedCatalogueId = null;
lock = false;
}
/**
* Keeping lock when changing one sub catalogue display state.
* This method is used to check if the changing process has been finished.
*/
var whenCheckOpenNew = function(catalogueId)
{
// If opening process hasn't been finished, return.
if (lastOpenedCatalogueId != null && eachCatalogueStatus[lastOpenedCatalogueId].open
|| !(eachCatalogueStatus[catalogueId].open)) { return; }
var checkThreadId = eachCatalogueStatus[catalogueId].checkThreadId;
if (checkThreadId) { clearInterval(checkThreadId); }
lastOpenedCatalogueId = catalogueId;
lock = false;
}
|