98 lines
3.9 KiB
Plaintext
98 lines
3.9 KiB
Plaintext
component {
|
|
|
|
/**
|
|
* HSQL 1.8
|
|
* Принимает Lucee Query, создает в HSQL временную таблицу и льет в нее данные
|
|
* @name Имя таблицы, которое ты хочешь использовать в SQL
|
|
* @data Сам запрос (результат queryExecute или cfhttp)
|
|
* @dsn Имя datasource для HSQL (по умолчанию "inmem")
|
|
*/
|
|
public string function register(required string name, required query data, string dsn = "inmem") {
|
|
var cols = arguments.data.columnList;
|
|
var meta = getMetaData(arguments.data);
|
|
|
|
//writedump(meta);
|
|
var colDefs = [];
|
|
var colTypes = {};
|
|
var params = [];
|
|
|
|
// 1. Генерируем "CREATE TEMP TABLE name (col1 TYPE, col2 TYPE...)"
|
|
for (var i = 1; i <= arrayLen(meta); i++) {
|
|
var colName = meta[i].name;
|
|
// Маппинг типов Lucee -> типы H2
|
|
var dbType = mapType(meta[i].typeName);
|
|
arrayAppend(colDefs, "#colName# #dbType#");
|
|
colTypes[colName] = meta[i].typeName;
|
|
}
|
|
//writedump(colDefs);
|
|
//var checkSql = "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_TABLES WHERE TABLE_NAME = '#ucase(arguments.name)#';"
|
|
//var res = queryExecute(checkSql, {}, { datasource: arguments.dsn });
|
|
|
|
//if (res.recordCount EQ 0) {
|
|
var createSql = "DROP TABLE IF EXISTS #arguments.name#;
|
|
CREATE TEMPORARY TABLE #arguments.name#(#arrayToList(colDefs, ', ')#) ON COMMIT PRESERVE ROWS";
|
|
queryExecute(createSql, {}, { datasource: arguments.dsn });
|
|
//}
|
|
|
|
// 2. Цикл вставки
|
|
var insertSql = "INSERT INTO #arguments.name# (#cols#) VALUES (#repeatString("?,", listLen(cols)-1)#?)";
|
|
|
|
for (var row in arguments.data) {
|
|
var rowData = [];
|
|
for (var col in cols) {
|
|
|
|
arrayAppend(rowData, formatValue(row[col], colTypes[col]));
|
|
}
|
|
|
|
queryExecute(insertSql, rowData, { datasource: arguments.dsn });
|
|
}
|
|
|
|
return arguments.name;
|
|
}
|
|
|
|
/**
|
|
* Удалить временные таблицы (опционально, база сама почистит при закрытии коннекта)
|
|
*/
|
|
public void function drop(required string names, string dsn = "inmem") {
|
|
var list = arguments.names;
|
|
if (!isArray(list)) list = [list];
|
|
for (var name in list) {
|
|
queryExecute("DROP TABLE IF EXISTS #name#", {}, { datasource: arguments.dsn });
|
|
}
|
|
}
|
|
|
|
// --- Вспомогательная функция маппинга типов ---
|
|
private string function mapType(required string luceeType) {
|
|
switch (arguments.luceeType) {
|
|
case "VARCHAR": case "CHAR": case "LONGVARCHAR": return "LONGVARCHAR";
|
|
case "INTEGER": case "BIGINT": case "SMALLINT": case "TINYINT": return "INT";
|
|
case "DOUBLE": case "FLOAT": case "REAL": return "DOUBLE";
|
|
case "BOOLEAN": case "BIT": return "BIT";
|
|
case "DECIMAL": case "NUMERIC": return "DECIMAL(20,6)";
|
|
default: return "LONGVARCHAR"; // И тут тоже
|
|
}
|
|
}
|
|
|
|
private function formatValue(required any val, required string targetType) {
|
|
var isTextType = listFindNoCase("VARCHAR,CHAR,LONGVARCHAR", arguments.targetType);
|
|
|
|
// 1. Обработка пустых значений
|
|
if (isNull(arguments.val) || (isSimpleValue(arguments.val) && len(trim(arguments.val)) == 0)) {
|
|
// Если это текстовое поле — сохраняем пустую строку как есть
|
|
if (isTextType) {
|
|
return "";
|
|
}
|
|
// Для чисел, дат и булев — отдаем настоящий SQL NULL
|
|
return javaCast("null", "");
|
|
}
|
|
|
|
// 2. Форматирование непустых дат
|
|
if (listFindNoCase("DATE,TIMESTAMP,TIME", arguments.targetType)) {
|
|
return dateFormat(arguments.val, "yyyy-mm-dd") & " " & timeFormat(arguments.val, "HH:mm:ss");
|
|
}
|
|
|
|
// 3. Числа и непустой текст отдаем как есть
|
|
return arguments.val;
|
|
}
|
|
|
|
} |