Skip to content

Commit 3ed7ded

Browse files
authored
Merge 37bd9db into 33ba54d
2 parents 33ba54d + 37bd9db commit 3ed7ded

File tree

3 files changed

+110
-16
lines changed

3 files changed

+110
-16
lines changed

ydb/core/kqp/provider/yql_kikimr_datasink.cpp

+42-3
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ class TKikimrDataSink : public TDataProviderBase
787787
auto replaceIfExists = (settings.Mode.Cast().Value() == "create_or_replace");
788788
auto existringOk = (settings.Mode.Cast().Value() == "create_if_not_exists");
789789

790-
return Build<TKiCreateTable>(ctx, node->Pos())
790+
auto createTable = Build<TKiCreateTable>(ctx, node->Pos())
791791
.World(node->Child(0))
792792
.DataSink(node->Child(1))
793793
.Table().Build(key.GetTablePath())
@@ -807,8 +807,47 @@ class TKikimrDataSink : public TDataProviderBase
807807
.ExistingOk<TCoAtom>()
808808
.Value(existringOk)
809809
.Build()
810-
.Done()
811-
.Ptr();
810+
.Done();
811+
812+
bool exprEvalNeeded = false;
813+
814+
for(auto item: createTable.Cast<TKiCreateTable>().Columns()) {
815+
auto columnTuple = item.Cast<TExprList>();
816+
if (columnTuple.Size() > 2) {
817+
const auto& columnConstraints = columnTuple.Item(2).Cast<TCoNameValueTuple>();
818+
for(const auto& constraint: columnConstraints.Value().Cast<TCoNameValueTupleList>()) {
819+
if (constraint.Name().Value() != "default")
820+
continue;
821+
822+
YQL_ENSURE(constraint.Value().IsValid());
823+
bool shouldEvaluate = (
824+
constraint.Value().Cast().Ptr()->IsCallable() &&
825+
(constraint.Value().Cast().Ptr()->Content() == "PgCast") &&
826+
(constraint.Value().Cast().Ptr()->ChildrenSize() >= 1) &&
827+
(constraint.Value().Cast().Ptr()->Child(0)->IsCallable()) &&
828+
(constraint.Value().Cast().Ptr()->Child(0)->Content() == "PgConst")
829+
);
830+
831+
if (shouldEvaluate) {
832+
auto evaluatedExpr = ctx.Builder(constraint.Value().Cast().Ptr()->Pos())
833+
.Callable("EvaluateExpr")
834+
.Add(0, constraint.Value().Cast().Ptr())
835+
.Seal()
836+
.Build();
837+
838+
constraint.Ptr()->ChildRef(TCoNameValueTuple::idx_Value) = evaluatedExpr;
839+
exprEvalNeeded = true;
840+
}
841+
}
842+
}
843+
}
844+
845+
if (exprEvalNeeded) {
846+
ctx.Step.Repeat(TExprStep::ExprEval);
847+
}
848+
849+
return createTable.Ptr();
850+
812851
} else if (mode == "alter") {
813852
for (auto setting : settings.Other) {
814853
if (setting.Name().Value() == "intent") {

ydb/core/kqp/provider/yql_kikimr_type_ann.cpp

+25-13
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,13 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
808808

809809
columnMeta.SetDefaultFromLiteral();
810810

811-
if (auto pgConst = constraint.Value().Maybe<TCoPgConst>()) {
811+
YQL_ENSURE(constraint.Value().IsValid());
812+
const auto& constrValue = constraint.Value().Cast();
813+
bool isPgNull = constrValue.Ptr()->IsCallable() &&
814+
constrValue.Ptr()->Content() == "PgCast" && constrValue.Ptr()->ChildrenSize() >= 1 &&
815+
constrValue.Ptr()->Child(0)->IsCallable() && constrValue.Ptr()->Child(0)->Content() == "Null";
816+
817+
if (constrValue.Maybe<TCoPgConst>() || isPgNull) {
812818
auto actualPgType = actualType->Cast<TPgExprType>();
813819
YQL_ENSURE(actualPgType);
814820

@@ -819,25 +825,31 @@ virtual TStatus HandleCreateTable(TKiCreateTable create, TExprContext& ctx) over
819825
return TStatus::Error;
820826
}
821827

822-
TString content = TString(pgConst.Cast().Value().Value());
823-
auto parseResult = NKikimr::NPg::PgNativeBinaryFromNativeText(content, typeDesc);
824-
if (parseResult.Error) {
825-
ctx.AddError(TIssue(ctx.GetPosition(constraint.Pos()),
826-
TStringBuilder() << "Failed to parse default expr for typename " << actualPgType->GetName()
827-
<< ", error reason: " << *parseResult.Error));
828-
return TStatus::Error;
828+
if (isPgNull) {
829+
columnMeta.DefaultFromLiteral.mutable_value()->set_null_flag_value(NProtoBuf::NULL_VALUE);
830+
} else {
831+
YQL_ENSURE(constrValue.Maybe<TCoPgConst>());
832+
auto pgConst = constrValue.Cast<TCoPgConst>();
833+
TString content = TString(pgConst.Value().Value());
834+
auto parseResult = NKikimr::NPg::PgNativeBinaryFromNativeText(content, typeDesc);
835+
if (parseResult.Error) {
836+
ctx.AddError(TIssue(ctx.GetPosition(constraint.Pos()),
837+
TStringBuilder() << "Failed to parse default expr for typename " << actualPgType->GetName()
838+
<< ", error reason: " << *parseResult.Error));
839+
return TStatus::Error;
840+
}
841+
842+
columnMeta.DefaultFromLiteral.mutable_value()->set_bytes_value(parseResult.Str);
829843
}
830844

831-
columnMeta.DefaultFromLiteral.mutable_value()->set_bytes_value(parseResult.Str);
832845
auto* pg = columnMeta.DefaultFromLiteral.mutable_type()->mutable_pg_type();
833-
834846
pg->set_type_name(NKikimr::NPg::PgTypeNameFromTypeDesc(typeDesc));
835847
pg->set_oid(NKikimr::NPg::PgTypeIdFromTypeDesc(typeDesc));
836-
} else if (auto literal = constraint.Value().Maybe<TCoDataCtor>()) {
837-
FillLiteralProto(constraint.Value().Cast<TCoDataCtor>(), columnMeta.DefaultFromLiteral);
848+
} else if (auto literal = constrValue.Maybe<TCoDataCtor>()) {
849+
FillLiteralProto(literal.Cast(), columnMeta.DefaultFromLiteral);
838850
} else {
839851
ctx.AddError(TIssue(ctx.GetPosition(constraint.Pos()),
840-
TStringBuilder() << "Unsupported type of default value " << constraint.Value().Cast().Ptr()->Content()));
852+
TStringBuilder() << "Unsupported type of default value"));
841853
return TStatus::Error;
842854
}
843855

ydb/core/kqp/ut/pg/kqp_pg_ut.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -3401,6 +3401,49 @@ Y_UNIT_TEST_SUITE(KqpPg) {
34013401
}
34023402
}
34033403

3404+
Y_UNIT_TEST(InsertValuesFromTableWithDefaultAndCast) {
3405+
NKikimrConfig::TAppConfig appConfig;
3406+
appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);
3407+
auto setting = NKikimrKqp::TKqpSetting();
3408+
auto serverSettings = TKikimrSettings()
3409+
.SetAppConfig(appConfig)
3410+
.SetKqpSettings({setting});
3411+
TKikimrRunner kikimr(serverSettings.SetWithSampleTables(false));
3412+
auto db = kikimr.GetQueryClient();
3413+
auto settings = NYdb::NQuery::TExecuteQuerySettings().Syntax(NYdb::NQuery::ESyntax::Pg);
3414+
{
3415+
auto result = db.ExecuteQuery(R"(
3416+
CREATE TABLE t (
3417+
a INT,
3418+
b int DEFAULT 5::int4,
3419+
c int DEFAULT '7'::int4,
3420+
d varchar(20) DEFAULT 'foo'::varchar(2),
3421+
e int DEFAULT NULL,
3422+
f bit varying(5) DEFAULT '1001',
3423+
PRIMARY KEY(a)
3424+
);
3425+
)", NYdb::NQuery::TTxControl::NoTx(), settings).ExtractValueSync();
3426+
UNIT_ASSERT_C(result.IsSuccess(), result.GetIssues().ToString());
3427+
}
3428+
{
3429+
auto result = db.ExecuteQuery(R"(
3430+
INSERT INTO t VALUES(1);
3431+
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
3432+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
3433+
}
3434+
{
3435+
auto result = db.ExecuteQuery(R"(
3436+
SELECT * FROM t;
3437+
)", NYdb::NQuery::TTxControl::BeginTx().CommitTx(), settings).ExtractValueSync();
3438+
UNIT_ASSERT_VALUES_EQUAL_C(result.GetStatus(), EStatus::SUCCESS, result.GetIssues().ToString());
3439+
3440+
UNIT_ASSERT_C(!result.GetResultSets().empty(), "results are empty");
3441+
CompareYson(R"(
3442+
[["1";"5";"7";"fo";#;"1001"]]
3443+
)", FormatResultSetYson(result.GetResultSet(0)));
3444+
}
3445+
}
3446+
34043447
Y_UNIT_TEST(InsertValuesFromTableWithDefaultBool) {
34053448
NKikimrConfig::TAppConfig appConfig;
34063449
appConfig.MutableTableServiceConfig()->SetEnablePreparedDdl(true);

0 commit comments

Comments
 (0)